From 0614ed72264dc1ff85e65e49104c5dfc35cb35a4 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Wed, 6 Nov 2024 17:42:17 +0100 Subject: [PATCH 001/464] net: revert virtio-net queue size to 256 Changing the queue size from 256 to 512 increases RX throughput but seems to regress TX throughput by 3% on average. We are not sure what is causing this. Revert this change until we have enough time to investigate and understand better the mechanisms that are in play. Signed-off-by: Babis Chalios --- CHANGELOG.md | 4 ---- src/vmm/src/devices/virtio/net/mod.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0ab56b4db0..2767c3dbf99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,10 +33,6 @@ and this project adheres to ### Changed -- [#4875](https://github.com/firecracker-microvm/firecracker/pull/4875): - Increase default queue size for the `virtio-net` device from 256 to 512. This - decreases wait time between guest and vmm threads for network packets - processing and allows for more throughput. - [#4844](https://github.com/firecracker-microvm/firecracker/pull/4844): Upgrade `virtio-net` device to use `readv` syscall to avoid unnecessary memory copies on RX path, increasing the RX performance. diff --git a/src/vmm/src/devices/virtio/net/mod.rs b/src/vmm/src/devices/virtio/net/mod.rs index 197f2069d47..4bc5b896601 100644 --- a/src/vmm/src/devices/virtio/net/mod.rs +++ b/src/vmm/src/devices/virtio/net/mod.rs @@ -6,7 +6,7 @@ use std::io; /// Maximum size of the queue for network device. -pub const NET_QUEUE_MAX_SIZE: u16 = 512; +pub const NET_QUEUE_MAX_SIZE: u16 = 256; /// Maximum size of the frame buffers handled by this device. pub const MAX_BUFFER_SIZE: usize = 65562; /// The number of queues of the network device. From 8c712d2bfa672f495ad9d7becb189dde9f43126b Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Thu, 7 Nov 2024 10:01:45 +0000 Subject: [PATCH 002/464] chore: bump version to 1.11.0-dev bump version to 1.11.0-dev Signed-off-by: Jack Thomson --- Cargo.lock | 12 ++++++------ src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 2 +- src/firecracker/swagger/firecracker.yaml | 2 +- src/jailer/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad43f6af62c..a26db6fbf6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "cpu-template-helper" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "clap", "displaydoc", @@ -606,7 +606,7 @@ dependencies = [ [[package]] name = "firecracker" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "bincode", "cargo_toml", @@ -800,7 +800,7 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jailer" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "libc", "log-instrument", @@ -1140,7 +1140,7 @@ dependencies = [ [[package]] name = "rebase-snap" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "displaydoc", "libc", @@ -1215,7 +1215,7 @@ dependencies = [ [[package]] name = "seccompiler" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "bincode", "displaydoc", @@ -1295,7 +1295,7 @@ dependencies = [ [[package]] name = "snapshot-editor" -version = "1.10.0-dev" +version = "1.11.0-dev" dependencies = [ "clap", "clap-num", diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index a5f06010aed..e3fd0ba68ae 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpu-template-helper" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 28aeda87a8c..47184c15eb8 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "firecracker" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" build = "build.rs" diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index 869e8758fdf..06f449db431 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -5,7 +5,7 @@ info: The API is accessible through HTTP calls on specific URLs carrying JSON modeled data. The transport medium is a Unix Domain Socket. - version: 1.10.0-dev + version: 1.11.0-dev termsOfService: "" contact: email: "compute-capsule@amazon.com" diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 373c8d5e172..8cb6c219be3 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jailer" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" description = "Process for starting Firecracker in production scenarios; applies a cgroup/namespace isolation barrier and then drops privileges." diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index e962c912668..a5eb21c7f20 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rebase-snap" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 5854f9fb67d..818f9e41fe2 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "seccompiler" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" description = "Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file." diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 7c341cbfd13..0b9b26cd66f 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snapshot-editor" -version = "1.10.0-dev" +version = "1.11.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" From 1f07842de48c248abe9f438ea82d826f5beaf02a Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 7 Nov 2024 12:34:28 +0000 Subject: [PATCH 003/464] test(net): check output in test_high_ingress_traffic If we supply an invalid iperf binary to the test it still passes. This adds checks for the command output. While doing that, increase the timeout to let the command finish without hitting it. Signed-off-by: Nikita Kalyazin --- tests/integration_tests/functional/test_net.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 12980c727b2..91d3c6716db 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -33,13 +33,13 @@ def test_high_ingress_traffic(uvm_plain_any): test_microvm.start() # Start iperf3 server on the guest. - test_microvm.ssh.run("{} -sD\n".format(IPERF_BINARY)) + test_microvm.ssh.check_output("{} -sD\n".format(IPERF_BINARY)) time.sleep(1) # Start iperf3 client on the host. Send 1Gbps UDP traffic. # If the net device breaks, iperf will freeze. We have to use a timeout. - utils.run_cmd( - "timeout 30 {} {} -c {} -u -V -b 1000000000 -t 30".format( + utils.check_output( + "timeout 31 {} {} -c {} -u -V -b 1000000000 -t 30".format( test_microvm.netns.cmd_prefix(), IPERF_BINARY, guest_ip, From 2e994b5855993896e04694b3db46f5c2112dfde1 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 7 Nov 2024 12:38:50 +0000 Subject: [PATCH 004/464] test(net): use iperf3-vsock in test_high_ingress_traffic We observe iperf3 3.16+ crashes on aarch64 when running the test. Use iperf3-vsock that we already build from source instead. Signed-off-by: Nikita Kalyazin --- tests/integration_tests/functional/test_net.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 91d3c6716db..e52389bc8b8 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -10,7 +10,11 @@ from framework import utils # The iperf version to run this tests with -IPERF_BINARY = "iperf3" +IPERF_BINARY_GUEST = "iperf3" +# We are using iperf3-vsock instead of a regular iperf3, +# because iperf3 3.16+ crashes on aarch64 sometimes +# when running this test. +IPERF_BINARY_HOST = "iperf3-vsock" def test_high_ingress_traffic(uvm_plain_any): @@ -33,7 +37,7 @@ def test_high_ingress_traffic(uvm_plain_any): test_microvm.start() # Start iperf3 server on the guest. - test_microvm.ssh.check_output("{} -sD\n".format(IPERF_BINARY)) + test_microvm.ssh.check_output("{} -sD\n".format(IPERF_BINARY_GUEST)) time.sleep(1) # Start iperf3 client on the host. Send 1Gbps UDP traffic. @@ -41,7 +45,7 @@ def test_high_ingress_traffic(uvm_plain_any): utils.check_output( "timeout 31 {} {} -c {} -u -V -b 1000000000 -t 30".format( test_microvm.netns.cmd_prefix(), - IPERF_BINARY, + IPERF_BINARY_HOST, guest_ip, ), ) From f2ddc049db2417d58e2230b6c368c9f3a6234dfb Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 7 Nov 2024 10:54:29 +0000 Subject: [PATCH 005/464] fix(test): Handle ssbs correctly in host/guest feature comparison Linux kernel should hide "ssbs" since Neoverse-N1 and Neoverse-V1 have an errata whereby an MSR to the SSBS special-purpose register does not affect subsequent speculative instructions, permitting speculative store bypassing for a window of time. Although Amazon Linux host kernels (v5.10 and v6.1) backported it, the guest kernels (v5.10 and v6.1) and the ubuntu host kernel (currently v6.8) lack the change. Fixes: 2babc80fe4b ("test(aarch64): add host vs guest cpu feature test") Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_aarch64.py | 59 +++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 3bfa2357d8b..fd04b17c305 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -10,6 +10,7 @@ import framework.utils_cpuid as cpuid_utils from framework import utils +from framework.properties import global_props from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel PLATFORM = platform.machine() @@ -81,25 +82,63 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): cpu_model = cpuid_utils.get_cpu_model_name() match cpu_model: case CpuModel.ARM_NEOVERSE_N1: - assert host_feats - guest_feats == set() - # Kernel should hide this feature, but our guest kernel - # currently lacks the commit with this change. - # The commit that introduces the change: - # https://github.com/torvalds/linux/commit/7187bb7d0b5c7dfa18ca82e9e5c75e13861b1d88 - assert guest_feats - host_feats == {"ssbs"} + expected_guest_minus_host = set() + expected_host_minus_guest = set() + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host case CpuModel.ARM_NEOVERSE_V1: + expected_guest_minus_host = set() # KVM does not enable PAC or SVE features by default # and Firecracker does not enable them either. - assert host_feats - guest_feats == { + expected_host_minus_guest = { "paca", "pacg", "sve", "svebf16", "svei8mm", } - # kernel should hide this feature, but our guest kernel - # is not recent enough for this. - assert guest_feats - host_feats == {"ssbs"} + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host case _: if os.environ.get("BUILDKITE") is not None: assert False, f"Cpu model {cpu_model} is not supported" From f51fbd5172d661615fec11dbe7537d516576b8d7 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 7 Nov 2024 12:29:35 +0000 Subject: [PATCH 006/464] fix(test): Remove flush_l1d from host/guest feature diff on kernel v6.4+ Linux kernel v6.4+ passes through the "l1d_flush" CPUID bit to guests. While the ubuntu host kernel (v6.8) has the change, the latest Amazon Linux 2 and Amazon Linux 2023 doesn't. Fixes: 4e014a1c9a93 ("test(x86_64): add host vs guest cpu feature test") Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_x86_64.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 3cea004a6b4..50475fc94e8 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -343,7 +343,7 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "umip", } case CpuModel.INTEL_CASCADELAKE: - assert host_feats - guest_feats == { + expected = { "acpi", "aperfmperf", "arch_perfmon", @@ -392,6 +392,14 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "vpid", "xtpr", } + # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. + # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e + # + # Our test ubuntu host kernel is v6.8 and has the commit. + if global_props.host_linux_version_tpl >= (6, 4): + expected -= {"flush_l1d"} + assert host_feats - guest_feats == expected + assert guest_feats - host_feats == { "hypervisor", "tsc_known_freq", From cbe79eaa516b201aa9158ee99f03e0e72c2a23ac Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 7 Nov 2024 13:53:27 +0000 Subject: [PATCH 007/464] fix(test): Handle invpcid_single in guest/host feature comparison Linux kernel v6.6+ drops the synthetic feature flag. While the ubuntu host kernel (v6.8) has the change, the Amazon Linux kernels (v5.10 and v6.1) and the guest kernels (v5.10 and v6.1) don't. Fixes: 4e014a1c9a93 ("test(x86_64): add host vs guest cpu feature test") Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_x86_64.py | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) 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 50475fc94e8..3174e9dda6c 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -343,7 +343,7 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "umip", } case CpuModel.INTEL_CASCADELAKE: - expected = { + expected_host_minus_guest = { "acpi", "aperfmperf", "arch_perfmon", @@ -392,19 +392,32 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "vpid", "xtpr", } + expected_guest_minus_host = { + "hypervisor", + "tsc_known_freq", + "umip", + } + # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e # # Our test ubuntu host kernel is v6.8 and has the commit. if global_props.host_linux_version_tpl >= (6, 4): - expected -= {"flush_l1d"} - assert host_feats - guest_feats == expected + expected_host_minus_guest -= {"flush_l1d"} - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - "umip", - } + # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit. + # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d + # + # Our test ubuntu host kernel is v6.8 and has the commit. + host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6) + guest_has_invpcid_single = vm.guest_kernel_version < (6, 6) + if host_has_invpcid_single and not guest_has_invpcid_single: + expected_host_minus_guest |= {"invpcid_single"} + if not host_has_invpcid_single and guest_has_invpcid_single: + expected_guest_minus_host |= {"invpcid_single"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host case CpuModel.INTEL_ICELAKE: host_guest_diff_5_10 = { "dtes64", From c75c86103d464f61851134eb3211b35323be4ffc Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Fri, 8 Nov 2024 10:50:05 +0000 Subject: [PATCH 008/464] chore: Update changelog with v1.10.0 section Update with v1.10.0 section Signed-off-by: Jack Thomson --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2767c3dbf99..f0a82d9986e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,18 @@ and this project adheres to ### Added +### Changed + +### Deprecated + +### Removed + +### Fixed + +## \[1.10.0\] + +### Added + - [#4834](https://github.com/firecracker-microvm/firecracker/pull/4834): Add `VIRTIO_NET_F_RX_MRGBUF` support to the `virtio-net` device. When this feature is negotiated, guest `virtio-net` driver can perform more efficient memory From bcfefab76df9353a7762023f8c885dccde749f5a Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 8 Nov 2024 14:24:58 +0000 Subject: [PATCH 009/464] chore(test): Double refill time for RX rate limiter Although we increased the refill time in the past in commit 347f877ec2a9 ("unittest: net: eliminate ReadTapMock::MockFrame") to avoid intermittent issues, it still fails rarely (maybe due to resource contention). We are not sure the enough refill time, but it's worth a try and may reduce the chance of kicking the retry of the whole unit tests manually. Signed-off-by: Takahiro Itazuri --- src/vmm/src/devices/virtio/net/device.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 6c69bd171a7..967b70092c8 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -2153,7 +2153,7 @@ pub mod tests { // Test RX bandwidth rate limiting { // create bandwidth rate limiter that allows 2000 bytes/s with bucket size 1000 bytes - let mut rl = RateLimiter::new(1000, 0, 500, 0, 0, 0).unwrap(); + let mut rl = RateLimiter::new(1000, 0, 1000, 0, 0, 0).unwrap(); // set up RX assert!(th.net().rx_buffer.used_descriptors == 0); @@ -2195,9 +2195,9 @@ pub mod tests { assert_eq!(th.net().metrics.rx_rate_limiter_throttled.count(), 2); } - // wait for 500ms to give the rate-limiter timer a chance to replenish - // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel - thread::sleep(Duration::from_millis(1000)); + // wait for 1000ms to give the rate-limiter timer a chance to replenish + // wait for an extra 1000ms to make sure the timerfd event makes its way from the kernel + thread::sleep(Duration::from_millis(2000)); // following RX procedure should succeed because bandwidth should now be available { @@ -2276,7 +2276,7 @@ pub mod tests { // Test RX ops rate limiting { // create ops rate limiter that allows 2 ops/s with bucket size 1 ops - let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 500).unwrap(); + let mut rl = RateLimiter::new(0, 0, 0, 1, 0, 1000).unwrap(); // set up RX assert!(th.net().rx_buffer.used_descriptors == 0); @@ -2319,9 +2319,9 @@ pub mod tests { assert_eq!(th.rxq.used.idx.get(), 0); } - // wait for 500ms to give the rate-limiter timer a chance to replenish - // wait for an extra 500ms to make sure the timerfd event makes its way from the kernel - thread::sleep(Duration::from_millis(1000)); + // wait for 1000ms to give the rate-limiter timer a chance to replenish + // wait for an extra 1000ms to make sure the timerfd event makes its way from the kernel + thread::sleep(Duration::from_millis(2000)); // following RX procedure should succeed because ops should now be available { From 841de95fb8ff29772aeca88aec64747e8c203446 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 4 Nov 2024 12:22:29 +0000 Subject: [PATCH 010/464] fix(net): use correct constant for preallocation Use `NET_QUEUE_SIZES` for `parsed_descriptors` in the `RxBuffers` instead of `FIRECRACKER_MAX_QUEUE_SIZE` Signed-off-by: Egor Lazarchuk --- src/vmm/src/devices/virtio/net/device.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 967b70092c8..818fed86a30 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -31,7 +31,7 @@ use crate::devices::virtio::net::tap::Tap; use crate::devices::virtio::net::{ gen, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX, }; -use crate::devices::virtio::queue::{DescriptorChain, Queue, FIRECRACKER_MAX_QUEUE_SIZE}; +use crate::devices::virtio::queue::{DescriptorChain, Queue}; use crate::devices::virtio::{ActivateError, TYPE_NET}; use crate::devices::{report_net_event_fail, DeviceError}; use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN; @@ -119,7 +119,7 @@ impl RxBuffers { Ok(Self { min_buffer_size: 0, iovec: IoVecBufferMut::new()?, - parsed_descriptors: VecDeque::with_capacity(FIRECRACKER_MAX_QUEUE_SIZE.into()), + parsed_descriptors: VecDeque::with_capacity(NET_QUEUE_MAX_SIZE.into()), used_descriptors: 0, used_bytes: 0, }) From 79bf1297c78b080b804f9b10168d3693622b940f Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 4 Nov 2024 12:29:43 +0000 Subject: [PATCH 011/464] fix(iovec): update default used constants Use `FIRECRACKER_MAX_QUEUE_SIZE` for default type alias. Use `L` const generic in the stub for `push_back` for kani. Signed-off-by: Egor Lazarchuk --- src/vmm/src/devices/virtio/iovec.rs | 38 +++++++++++++++-------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index 4cbbc512186..2161d7273ef 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -482,10 +482,12 @@ mod tests { use super::IoVecBuffer; // Redefine `IoVecBufferMut` with specific length. Otherwise // Rust will not know what to do. - type IoVecBufferMut = super::IoVecBufferMut<256>; + type IoVecBufferMutDefault = super::IoVecBufferMut; use crate::devices::virtio::iov_deque::IovDeque; - use crate::devices::virtio::queue::{Queue, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; + use crate::devices::virtio::queue::{ + Queue, FIRECRACKER_MAX_QUEUE_SIZE, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE, + }; use crate::devices::virtio::test_utils::VirtQueue; use crate::test_utils::multi_region_mem; use crate::vstate::memory::{Bytes, GuestAddress, GuestMemoryMmap}; @@ -614,12 +616,12 @@ mod tests { let (mut q, _) = read_only_chain(&mem); let head = q.pop().unwrap(); // SAFETY: This descriptor chain is only loaded into one buffer - unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap_err() }; + unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap_err() }; let (mut q, _) = write_only_chain(&mem); let head = q.pop().unwrap(); // SAFETY: This descriptor chain is only loaded into one buffer - unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() }; + unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() }; } #[test] @@ -640,7 +642,8 @@ mod tests { let head = q.pop().unwrap(); // SAFETY: This descriptor chain is only loaded once in this test - let mut iovec = unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() }; + let mut iovec = + unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() }; assert_eq!(iovec.len(), 4 * 64); // We are creating a new queue where we can get descriptors from. Probably, this is not @@ -717,7 +720,8 @@ mod tests { let head = q.pop().unwrap(); // SAFETY: This descriptor chain is only loaded into one buffer - let mut iovec = unsafe { IoVecBufferMut::from_descriptor_chain(&mem, head).unwrap() }; + let mut iovec = + unsafe { IoVecBufferMutDefault::from_descriptor_chain(&mem, head).unwrap() }; let buf = vec![0u8, 1, 2, 3, 4]; // One test vector for each part of the chain @@ -814,8 +818,8 @@ mod verification { use crate::devices::virtio::iov_deque::IovDeque; // Redefine `IoVecBufferMut` and `IovDeque` with specific length. Otherwise // Rust will not know what to do. - type IoVecBufferMut256 = super::IoVecBufferMut<256>; - type IovDeque256 = IovDeque<256>; + type IoVecBufferMutDefault = super::IoVecBufferMut; + type IovDequeDefault = IovDeque; use crate::arch::PAGE_SIZE; use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; @@ -860,10 +864,10 @@ mod verification { ); let offset = (deque.start + deque.len) as usize; - let mirror = if offset >= FIRECRACKER_MAX_QUEUE_SIZE as usize { - offset - FIRECRACKER_MAX_QUEUE_SIZE as usize + let mirror = if offset >= L as usize { + offset - L as usize } else { - offset + FIRECRACKER_MAX_QUEUE_SIZE as usize + offset + L as usize }; // SAFETY: self.iov is a valid pointer and `self.start + self.len` is within range (we @@ -904,7 +908,7 @@ mod verification { } } - fn create_iov_deque() -> IovDeque256 { + fn create_iov_deque() -> IovDequeDefault { // SAFETY: safe because the layout has non-zero size let mem = unsafe { std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked( @@ -912,14 +916,14 @@ mod verification { PAGE_SIZE, )) }; - IovDeque256 { + IovDequeDefault { iov: mem.cast(), start: kani::any_where(|&start| start < FIRECRACKER_MAX_QUEUE_SIZE), len: 0, } } - fn create_iovecs_mut(mem: *mut u8, size: usize, nr_descs: usize) -> (IovDeque256, u32) { + fn create_iovecs_mut(mem: *mut u8, size: usize, nr_descs: usize) -> (IovDequeDefault, u32) { let mut vecs = create_iov_deque(); let mut len = 0u32; for _ in 0..nr_descs { @@ -939,7 +943,7 @@ mod verification { (vecs, len) } - impl IoVecBufferMut256 { + impl IoVecBufferMutDefault { fn any_of_length(nr_descs: usize) -> Self { // We only write into `IoVecBufferMut` objects, so we can simply create a guest memory // object initialized to zeroes, trying to be nice to Kani. @@ -1029,12 +1033,10 @@ mod verification { #[kani::proof] #[kani::unwind(5)] #[kani::solver(cadical)] - // The `IovDeque` is defined as type alias in the kani module. Because of this - // we need to specify original type here for stub to work. #[kani::stub(IovDeque::push_back, stubs::push_back)] fn verify_write_to_iovec() { for nr_descs in 0..MAX_DESC_LENGTH { - let mut iov_mut = IoVecBufferMut256::any_of_length(nr_descs); + let mut iov_mut = IoVecBufferMutDefault::any_of_length(nr_descs); let mut buf = kani::vec::any_vec::(); let offset: u32 = kani::any(); From acc85f19c56b41e68ed14a6dbf6ba7fe80f6384e Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Tue, 12 Nov 2024 10:47:03 +0000 Subject: [PATCH 012/464] chore: Bump snapshot version Bump the snapshot version Signed-off-by: Jack Thomson --- CHANGELOG.md | 7 +++++++ src/vmm/src/persist.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a82d9986e..5ca0688ce06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,13 @@ and this project adheres to ### Fixed +## \[1.10.1\] + +### Changed + +- [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bump + snapshot version to 4.0.0. + ## \[1.10.0\] ### Added diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 560d9d7c6b7..16d7ed72537 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -157,7 +157,7 @@ pub enum CreateSnapshotError { } /// Snapshot version -pub const SNAPSHOT_VERSION: Version = Version::new(3, 0, 0); +pub const SNAPSHOT_VERSION: Version = Version::new(4, 0, 0); /// Creates a Microvm snapshot. pub fn create_snapshot( From a88f3b91899672b62402fb916397cd0ba1c61d73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:29:41 +0000 Subject: [PATCH 013/464] build(deps): Bump the firecracker group with 10 updates Bumps the firecracker group with 10 updates: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `1.0.67` | `2.0.3` | | [vm-memory](https://github.com/rust-vmm/vm-memory) | `0.16.0` | `0.16.1` | | [zerocopy](https://github.com/google/zerocopy) | `0.8.8` | `0.8.9` | | [libc](https://github.com/rust-lang/libc) | `0.2.161` | `0.2.162` | | [anstream](https://github.com/rust-cli/anstyle) | `0.6.17` | `0.6.18` | | [cc](https://github.com/rust-lang/cc-rs) | `1.1.34` | `1.1.37` | | [hashbrown](https://github.com/rust-lang/hashbrown) | `0.15.0` | `0.15.1` | | [regex-automata](https://github.com/rust-lang/regex) | `0.4.8` | `0.4.9` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.38` | `0.38.40` | | [thiserror-impl](https://github.com/dtolnay/thiserror) | `1.0.67` | `1.0.69` | Updates `thiserror` from 1.0.67 to 2.0.3 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.67...2.0.3) Updates `vm-memory` from 0.16.0 to 0.16.1 - [Release notes](https://github.com/rust-vmm/vm-memory/releases) - [Changelog](https://github.com/rust-vmm/vm-memory/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-vmm/vm-memory/compare/v0.16.0...v0.16.1) Updates `zerocopy` from 0.8.8 to 0.8.9 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/commits) Updates `libc` from 0.2.161 to 0.2.162 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.162/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.161...0.2.162) Updates `anstream` from 0.6.17 to 0.6.18 - [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.17...anstream-v0.6.18) Updates `cc` from 1.1.34 to 1.1.37 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.34...cc-v1.1.37) Updates `hashbrown` from 0.15.0 to 0.15.1 - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/compare/v0.15.0...v0.15.1) Updates `regex-automata` from 0.4.8 to 0.4.9 - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/commits/regex-automata-0.4.9) Updates `rustix` from 0.38.38 to 0.38.40 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.38...v0.38.40) Updates `thiserror-impl` from 1.0.67 to 1.0.69 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.67...1.0.69) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-major dependency-group: firecracker - dependency-name: vm-memory dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: anstream dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: hashbrown dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: regex-automata dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: thiserror-impl dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 96 ++++++++++++++++++------------ src/acpi-tables/Cargo.toml | 6 +- src/cpu-template-helper/Cargo.toml | 4 +- src/firecracker/Cargo.toml | 6 +- src/jailer/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 4 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 6 +- src/vmm/Cargo.toml | 8 +-- 10 files changed, 81 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a26db6fbf6e..fe779e26d13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,9 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror", + "thiserror 2.0.3", "vm-memory", - "zerocopy 0.8.8", + "zerocopy 0.8.9", ] [[package]] @@ -64,9 +64,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -261,9 +261,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.34" +version = "1.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" dependencies = [ "jobserver", "libc", @@ -426,7 +426,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "vmm", "vmm-sys-util", ] @@ -620,7 +620,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 2.0.3", "timerfd", "userfaultfd", "utils", @@ -707,9 +707,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "heck" @@ -806,7 +806,7 @@ dependencies = [ "log-instrument", "nix 0.29.0", "regex", - "thiserror", + "thiserror 2.0.3", "utils", "vmm-sys-util", ] @@ -857,9 +857,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libloading" @@ -1145,7 +1145,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror", + "thiserror 2.0.3", "utils", "vmm-sys-util", ] @@ -1164,9 +1164,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1187,9 +1187,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -1223,7 +1223,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "utils", "vmm-sys-util", ] @@ -1303,7 +1303,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror", + "thiserror 2.0.3", "utils", "vmm", "vmm-sys-util", @@ -1334,18 +1334,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.67" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3c6efbfc763e64eb85c11c25320f0737cb7364c4b6336db90aa9ebe27a0bbd" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.67" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b607164372e89797d78b8e23a6d67d5d1038c1c65efd52e1389ef8b77caba2a6" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -1455,7 +1475,7 @@ dependencies = [ "cfg-if", "libc", "nix 0.27.1", - "thiserror", + "thiserror 1.0.69", "userfaultfd-sys", ] @@ -1486,7 +1506,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "vm-memory", "vmm-sys-util", ] @@ -1539,7 +1559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e4ce718bd4e8d74b1747363e27f715a6b1bd6971597cb21425dadbf4e712241" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1550,12 +1570,12 @@ checksum = "7e21282841a059bb62627ce8441c491f09603622cd5a21c43bfedc85a2952f23" [[package]] name = "vm-memory" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2919f87420b6998a131eb7c78843890295e91a3f8f786ccc925c8d387b75121" +checksum = "f1720e7240cdc739f935456eb77f370d7e9b2a3909204da1e2b47bef1137a013" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", "winapi", ] @@ -1600,7 +1620,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror", + "thiserror 2.0.3", "timerfd", "userfaultfd", "utils", @@ -1610,7 +1630,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.8", + "zerocopy 0.8.9", ] [[package]] @@ -1787,11 +1807,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a4e33e6dce36f2adba29746927f8e848ba70989fdb61c772773bbdda8b5d6a7" +checksum = "f49e690f8f352f4a9ee8679a8c5921f42ffd0d6d6413a0a66b8e81cf524e109c" dependencies = [ - "zerocopy-derive 0.8.8", + "zerocopy-derive 0.8.9", ] [[package]] @@ -1807,9 +1827,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd137b4cc21bde6ecce3bbbb3350130872cda0be2c6888874279ea76e17d4c1" +checksum = "fa732fcc881df7a6fbe8e3ed17baadece53b379ad58fe2633396b1a2b108a7b1" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 4d066eb9338..5932faa732b 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,9 +8,9 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "1.0.67" -vm-memory = { version = "0.16.0", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.8", features = ["derive"] } +thiserror = "2.0.3" +vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } +zerocopy = { version = "0.8.9", features = ["derive"] } [lib] bench = false diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index e3fd0ba68ae..365945b6198 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -12,11 +12,11 @@ bench = false [dependencies] clap = { version = "4.5.20", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" -thiserror = "1.0.67" +thiserror = "2.0.3" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 47184c15eb8..39153386379 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -26,7 +26,7 @@ seccompiler = { path = "../seccompiler" } serde = { version = "1.0.214", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.132" -thiserror = "1.0.67" +thiserror = "2.0.3" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } @@ -34,7 +34,7 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.20.5" -libc = "0.2.161" +libc = "0.2.162" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 8cb6c219be3..95dc953ae77 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,11 +12,11 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "1.0.67" +thiserror = "2.0.3" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index a5eb21c7f20..1a0dab4c2a8 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,9 +11,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "1.0.67" +thiserror = "2.0.3" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 818f9e41fe2..91a556d8996 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,11 +18,11 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" -thiserror = "1.0.67" +thiserror = "2.0.3" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 0b9b26cd66f..af59a6c5e03 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -14,10 +14,10 @@ clap = { version = "4.5.20", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" -thiserror = "1.0.67" +thiserror = "2.0.3" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index cc0b979bfa6..bc792ac5801 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,11 +11,11 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.161" +libc = "0.2.162" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.214", features = ["derive"] } -thiserror = "1.0.67" -vm-memory = { version = "0.16.0", features = ["backend-mmap", "backend-bitmap"] } +thiserror = "2.0.3" +vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vmm-sys-util = "0.12.1" [dev-dependencies] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index c9a032edb95..2115b0e7253 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.161" +libc = "0.2.162" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -37,16 +37,16 @@ semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0.214", features = ["derive", "rc"] } serde_json = "1.0.132" slab = "0.4.7" -thiserror = "1.0.67" +thiserror = "2.0.3" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } vhost = { version = "0.13.0", features = ["vhost-user-frontend"] } vm-allocator = "0.1.0" -vm-memory = { version = "0.16.0", features = ["backend-mmap", "backend-bitmap"] } +vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.8" } +zerocopy = { version = "0.8.9" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 3f51da2de9fa40960feb40ca302d776ff6a8d0af Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 12 Nov 2024 12:54:53 +0000 Subject: [PATCH 014/464] fix: Adjust for thiserror 2.0 See https://github.com/dtolnay/thiserror/pull/354 Signed-off-by: Patrick Roy --- src/firecracker/src/api_server/parsed_request.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs index 125463d1d05..10405c156ec 100644 --- a/src/firecracker/src/api_server/parsed_request.rs +++ b/src/firecracker/src/api_server/parsed_request.rs @@ -276,7 +276,7 @@ pub(crate) enum RequestError { #[error("API Resource IDs can only contain alphanumeric characters and underscores.")] InvalidID, // The HTTP method & request path combination is not valid. - #[error("Invalid request method and/or path: {} {0}.", .1.to_str())] + #[error("Invalid request method and/or path: {} {}.", .1.to_str(), .0)] InvalidPathMethod(String, Method), // An error occurred when deserializing the json body of a request. #[error("An error occurred when deserializing the json body of a request: {0}.")] From 5a23130b77ffe807041914450795863e16673f55 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Tue, 12 Nov 2024 15:39:50 +0000 Subject: [PATCH 015/464] chore: update PR checklist Improve the PR checklist to make it more clear and explicitly ask contributors to run the automated checkstyles. Signed-off-by: Riccardo Mancini --- .github/pull_request_template.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1d6da74ba72..e05f0c2ae15 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -15,16 +15,20 @@ Certificate of Origin and signing off your commits, please check ## PR Checklist +- [ ] I have read and understand [CONTRIBUTING.md][3]. +- [ ] I have run `tools/devtool checkstyle` to verify that the PR passes the + automated style checks. +- [ ] I have described what is done in these changes, why they are needed, and + how they are solving the problem in a clear and encompassing way. +- [ ] I have updated any relevant documentation (both in code and in the docs) + in the PR. +- [ ] I have mentioned all user-facing changes in `CHANGELOG.md`. - [ ] If a specific issue led to this PR, this PR closes the issue. -- [ ] The description of changes is clear and encompassing. -- [ ] Any required documentation changes (code and docs) are included in this - PR. -- [ ] API changes follow the [Runbook for Firecracker API changes][2]. -- [ ] User-facing changes are mentioned in `CHANGELOG.md`. -- [ ] All added/changed functionality is tested. -- [ ] New `TODO`s link to an issue. -- [ ] Commits meet - [contribution quality standards](https://github.com/firecracker-microvm/firecracker/blob/main/CONTRIBUTING.md#contribution-quality-standards). +- [ ] When making API changes, I have followed the + [Runbook for Firecracker API changes][2]. +- [ ] I have tested all new and changed functionalities in unit tests and/or + integration tests. +- [ ] I have linked an issue to every new `TODO`. ______________________________________________________________________ From 1de16b32897c448f62bec9fb1f2248ae08d56f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 13 Nov 2024 10:54:57 +0100 Subject: [PATCH 016/464] test: test ARM CPU templates in Linux host 5.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the SVE CPU template as a valid template in 5.10 since it works. Signed-off-by: Pablo Barbáchano --- tests/framework/utils_cpu_templates.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 5badd7c640a..96bf197efda 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -42,18 +42,12 @@ def get_supported_cpu_templates(): SUPPORTED_CPU_TEMPLATES = get_supported_cpu_templates() -# Custom CPU templates for Aarch64 for testing -AARCH64_CUSTOM_CPU_TEMPLATES_G2 = ["v1n1"] -AARCH64_CUSTOM_CPU_TEMPLATES_G3 = [ - "aarch64_with_sve_and_pac", - "v1n1", -] - def get_supported_custom_cpu_templates(): """ Return the list of custom CPU templates supported by the platform. """ + # pylint:disable=too-many-return-statements host_linux = global_props.host_linux_version_tpl match get_cpu_vendor(), global_props.cpu_codename: @@ -65,9 +59,11 @@ def get_supported_custom_cpu_templates(): case CpuVendor.AMD, _: return AMD_TEMPLATES case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_N1 if host_linux >= (6, 1): - return AARCH64_CUSTOM_CPU_TEMPLATES_G2 + return ["v1n1"] case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V1 if host_linux >= (6, 1): - return AARCH64_CUSTOM_CPU_TEMPLATES_G3 + return ["v1n1", "aarch64_with_sve_and_pac"] + case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V1: + return ["aarch64_with_sve_and_pac"] case _: return [] From 32c6ed4b2fcca04438357a35ae5061fad31704bd Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 13 Nov 2024 11:53:26 +0000 Subject: [PATCH 017/464] chore: Update to v1.10.1 patch Update release policy to v1.10.1 patch Signed-off-by: Jack Thomson --- docs/RELEASE_POLICY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RELEASE_POLICY.md b/docs/RELEASE_POLICY.md index fb95c55e402..fe2f881d6b6 100644 --- a/docs/RELEASE_POLICY.md +++ b/docs/RELEASE_POLICY.md @@ -90,7 +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.10 | 2024-11-07 | v1.10.0 | 2025-05-07 | Supported | +| v1.10 | 2024-11-07 | v1.10.1 | 2025-05-07 | Supported | | v1.9 | 2024-09-02 | v1.9.1 | 2025-03-02 | Supported | | v1.8 | 2024-07-10 | v1.8.0 | 2025-01-10 | Supported | | v1.7 | 2024-03-18 | v1.7.0 | 2024-09-18 | 2024-09-18 (end of 6mo support) | From 588c7f056b5b43e991998612573deaca10b2209b Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 13 Nov 2024 11:07:12 +0000 Subject: [PATCH 018/464] snapshot: Remove max_connections and max_pending_resets fields `TcpIPv4Handler` for MMDS network stack preallocates several buffers whose sizes are saved into a snapshot as `max_connections` and `max_pending_resets` in `MmdsNetworkStackState`. But they are always the same constant hardcoded values (`DEFAULT_MAX_CONNECTIONS` and `DEFAULT_MAX_PENDING_RESETS`) as of today, which means there is no need to save them into a snapshot. Even if we change the hardcoded sizes across Firecracker versions, that should not be a problem. This is because the snapshot feature does not support migration of network connections and those buffers are initialized with empty on snapshot restoration. When migrating from a Firecracker version with larger buffers to another version with smaller ones, guest workloads that worked previously might start to fail due to the less buffer spaces. However, the issue is not a problem of the snapshot feature and it should also occur even on a purely booted microVM (not restored from a snapshot). Thus, it is fine to remove those fields from a snapshot. Since this is a breaking change of the snapshot format, bumps the major version. Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 4 ++++ src/vmm/src/mmds/ns.rs | 15 +++------------ src/vmm/src/mmds/persist.rs | 15 --------------- src/vmm/src/persist.rs | 2 +- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ca0688ce06..55c46a05276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to ### Changed +- [#4913](https://github.com/firecracker-microvm/firecracker/pull/4913): Removed + unnecessary fields (`max_connections` and `max_pending_resets`) from the + snapshot format, bumping the snapshot version to 5.0.0. + ### Deprecated ### Removed diff --git a/src/vmm/src/mmds/ns.rs b/src/vmm/src/mmds/ns.rs index 09d73b21e99..d431d71cbcb 100644 --- a/src/vmm/src/mmds/ns.rs +++ b/src/vmm/src/mmds/ns.rs @@ -81,8 +81,6 @@ impl MmdsNetworkStack { mac_addr: MacAddr, ipv4_addr: Ipv4Addr, tcp_port: u16, - max_connections: NonZeroUsize, - max_pending_resets: NonZeroUsize, mmds: Arc>, ) -> Self { MmdsNetworkStack { @@ -93,8 +91,8 @@ impl MmdsNetworkStack { tcp_handler: TcpIPv4Handler::new( ipv4_addr, tcp_port, - max_connections, - max_pending_resets, + NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(), + NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(), ), mmds, } @@ -105,14 +103,7 @@ impl MmdsNetworkStack { let ipv4_addr = mmds_ipv4_addr.unwrap_or_else(|| Ipv4Addr::from(DEFAULT_IPV4_ADDR)); // The unwrap()s are safe because the given literals are greater than 0. - Self::new( - mac_addr, - ipv4_addr, - DEFAULT_TCP_PORT, - NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(), - NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(), - mmds, - ) + Self::new(mac_addr, ipv4_addr, DEFAULT_TCP_PORT, mmds) } pub fn set_ipv4_addr(&mut self, ipv4_addr: Ipv4Addr) { diff --git a/src/vmm/src/mmds/persist.rs b/src/vmm/src/mmds/persist.rs index dc0113f8a5c..82feff79bc8 100644 --- a/src/vmm/src/mmds/persist.rs +++ b/src/vmm/src/mmds/persist.rs @@ -4,7 +4,6 @@ //! Defines the structures needed for saving/restoring MmdsNetworkStack. use std::net::Ipv4Addr; -use std::num::NonZeroUsize; use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; @@ -20,8 +19,6 @@ pub struct MmdsNetworkStackState { mac_addr: [u8; MAC_ADDR_LEN as usize], ipv4_addr: u32, tcp_port: u16, - max_connections: NonZeroUsize, - max_pending_resets: NonZeroUsize, } impl Persist<'_> for MmdsNetworkStack { @@ -37,8 +34,6 @@ impl Persist<'_> for MmdsNetworkStack { mac_addr, ipv4_addr: self.ipv4_addr.into(), tcp_port: self.tcp_handler.local_port(), - max_connections: self.tcp_handler.max_connections(), - max_pending_resets: self.tcp_handler.max_pending_resets(), } } @@ -50,8 +45,6 @@ impl Persist<'_> for MmdsNetworkStack { MacAddr::from_bytes_unchecked(&state.mac_addr), Ipv4Addr::from(state.ipv4_addr), state.tcp_port, - state.max_connections, - state.max_pending_resets, mmds, )) } @@ -83,13 +76,5 @@ mod tests { restored_ns.tcp_handler.local_port(), ns.tcp_handler.local_port() ); - assert_eq!( - restored_ns.tcp_handler.max_connections(), - ns.tcp_handler.max_connections() - ); - assert_eq!( - restored_ns.tcp_handler.max_pending_resets(), - ns.tcp_handler.max_pending_resets() - ); } } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 16d7ed72537..5b01ed49c75 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -157,7 +157,7 @@ pub enum CreateSnapshotError { } /// Snapshot version -pub const SNAPSHOT_VERSION: Version = Version::new(4, 0, 0); +pub const SNAPSHOT_VERSION: Version = Version::new(5, 0, 0); /// Creates a Microvm snapshot. pub fn create_snapshot( From bc4da15864a2150f07009e16ab640aab33973ab2 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 13 Nov 2024 10:46:22 +0000 Subject: [PATCH 019/464] test(mmds): Do not use MmdsNetworkStack::new() in tests There is no need to use MmdsNetworkStack::new() instead of MmdsNetworkStack::new_with_defaults() in tests that pass the same default values. Signed-off-by: Takahiro Itazuri --- src/vmm/src/mmds/ns.rs | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/vmm/src/mmds/ns.rs b/src/vmm/src/mmds/ns.rs index d431d71cbcb..8075df8cb91 100644 --- a/src/vmm/src/mmds/ns.rs +++ b/src/vmm/src/mmds/ns.rs @@ -553,14 +553,8 @@ mod tests { let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR); let other_ip = Ipv4Addr::new(5, 6, 7, 8); let mac = MacAddr::from_bytes_unchecked(&[0; 6]); - let mut ns = MmdsNetworkStack::new( - mac, - ip, - DEFAULT_TCP_PORT, - NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(), - NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(), - Arc::new(Mutex::new(Mmds::default())), - ); + let mut ns = + MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default()))); let mut eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap(); @@ -580,14 +574,8 @@ mod tests { let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR); let other_ip = Ipv4Addr::new(5, 6, 7, 8); let mac = MacAddr::from_bytes_unchecked(&[0; 6]); - let ns = MmdsNetworkStack::new( - mac, - ip, - DEFAULT_TCP_PORT, - NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(), - NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(), - Arc::new(Mutex::new(Mmds::default())), - ); + let ns = + MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default()))); let mut eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap(); @@ -606,14 +594,8 @@ mod tests { let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR); let other_ip = Ipv4Addr::new(5, 6, 7, 8); let mac = MacAddr::from_bytes_unchecked(&[0; 6]); - let mut ns = MmdsNetworkStack::new( - mac, - ip, - DEFAULT_TCP_PORT, - NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(), - NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(), - Arc::new(Mutex::new(Mmds::default())), - ); + let mut ns = + MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default()))); // try IPv4 with detour_arp let mut eth = From 83aec7b33553b72380ac3b8c84b73ec570b83600 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 14 Nov 2024 10:45:13 +0000 Subject: [PATCH 020/464] chore: Clarify user action We bumped the snapshot version up twice recently, requiring users to regenerate their snapshot, but the user action isn't clearly stated. Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55c46a05276..7da89123eab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ and this project adheres to - [#4913](https://github.com/firecracker-microvm/firecracker/pull/4913): Removed unnecessary fields (`max_connections` and `max_pending_resets`) from the - snapshot format, bumping the snapshot version to 5.0.0. + snapshot format, bumping the snapshot version to 5.0.0. Users need to + regenerate snapshots. ### Deprecated @@ -26,8 +27,8 @@ and this project adheres to ### Changed -- [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bump - snapshot version to 4.0.0. +- [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bumped + the snapshot version to 4.0.0, so users need to regenerate snapshots. ## \[1.10.0\] From ad9ec90b7d9de7579624c1c5df109485c9318eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Sep 2024 09:18:29 +0200 Subject: [PATCH 021/464] ci: generate ext4 image after downloading artifacts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids the need to store and download the image from S3. Signed-off-by: Pablo Barbáchano --- resources/rebuild.sh | 39 +++++++++---------------------------- tools/devtool | 6 ++---- tools/setup-ci-artifacts.sh | 30 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 34 deletions(-) create mode 100755 tools/setup-ci-artifacts.sh diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 9f6850d0555..cff8a314cd7 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -20,25 +20,6 @@ function install_dependencies { apt install -y bc flex bison gcc make libelf-dev libssl-dev squashfs-tools busybox-static tree cpio curl patch docker.io } -function dir2ext4img { - # ext4 - # https://unix.stackexchange.com/questions/503211/how-can-an-image-file-be-created-for-a-directory - local DIR=$1 - local IMG=$2 - # Default size for the resulting rootfs image is 300M - local SIZE=${3:-300M} - local TMP_MNT=$(mktemp -d) - truncate -s "$SIZE" "$IMG" - mkfs.ext4 -F "$IMG" - mount "$IMG" "$TMP_MNT" - tar c -C $DIR . |tar x -C "$TMP_MNT" - # cleanup - # Use the -l flag for lazy unmounting since sometimes umount fails - # with "device busy" and simply calling `sync` doesn't help - umount -l "$TMP_MNT" - rmdir $TMP_MNT -} - function prepare_docker { nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 & @@ -102,8 +83,6 @@ EOF rootfs_img="$OUTPUT_DIR/$ROOTFS_NAME.squashfs" mv $rootfs/root/manifest $OUTPUT_DIR/$ROOTFS_NAME.manifest mksquashfs $rootfs $rootfs_img -all-root -noappend - rootfs_ext4=$OUTPUT_DIR/$ROOTFS_NAME.ext4 - dir2ext4img $rootfs $rootfs_ext4 rm -rf $rootfs for bin in fast_page_fault_helper fillmem init readmem; do rm $PWD/overlay/usr/local/bin/$bin @@ -235,7 +214,7 @@ function build_al_kernels { local KERNEL_VERSION="all" elif [[ $# -ne 1 ]]; then die "Too many arguments in '$(basename $0) kernels' command. Please use \`$0 help\` for help." - else + else KERNEL_VERSION=$1 if [[ "$KERNEL_VERSION" != @(5.10|5.10-no-acpi|6.1) ]]; then die "Unsupported kernel version: '$KERNEL_VERSION'. Please use \`$0 help\` for help." @@ -259,7 +238,7 @@ function build_al_kernels { # Undo kernel patches on top of AL configuration git restore $PWD/guest_configs - rm -rf $PWD/guest_configs/*.orig + rm -rf $PWD/guest_configs/*.orig } function print_help { @@ -267,25 +246,25 @@ function print_help { Firecracker CI artifacts build script Usage: $(basename $0) [] [] - + Available commands: - + all (default) Build CI rootfs and default guest kernels using configurations from resources/guest_configs. This will patch the guest configurations with all the patches under resources/guest_configs/patches. This is the default command, if no command is chosen. - + rootfs Builds only the CI rootfs. - + kernels [version] Builds our the currently supported CI kernels. - + version: Optionally choose a kernel version to build. Supported versions are: 5.10, 5.10-no-acpi or 6.1. - + help Displays the help message and exits. EOF @@ -310,7 +289,7 @@ function main { fi set -x - + install_dependencies # Create the directory in which we will store the kernels and rootfs diff --git a/tools/devtool b/tools/devtool index e9eb3d48db0..6cd9c95e9c4 100755 --- a/tools/devtool +++ b/tools/devtool @@ -417,7 +417,7 @@ cmd_help() { echo " build_ci_artifacts [all|rootfs|kernels]" echo " Builds the rootfs and guest kernel artifacts we use for our CI." echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands." - echo "" + echo "" cat <]] @@ -567,9 +567,7 @@ ensure_ci_artifacts() { if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS aws s3 sync --no-sign-request "$S3_URL" "$ARTIFACTS" - # fix permissions - find "$ARTIFACTS" -type f -name "*.id_rsa" |xargs chmod -c 400 - find "$ARTIFACTS/firecracker" -type f |xargs chmod -c 755 + cmd_sh "./tools/setup-ci-artifacts.sh" fi } diff --git a/tools/setup-ci-artifacts.sh b/tools/setup-ci-artifacts.sh new file mode 100755 index 00000000000..5829fdd6fe1 --- /dev/null +++ b/tools/setup-ci-artifacts.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# fail if we encounter an error, uninitialized variable or a pipe breaks +set -eu -o pipefail + +TOOLS_DIR=$(dirname $0) +source "$TOOLS_DIR/functions" + +say "Setup CI artifacts" +cd build/img/$(uname -m) + +say "Fix executable permissions" +find "firecracker" -type f |xargs chmod -c 755 + +say "Fix RSA key permissions" +find . -type f -name "*.id_rsa" |xargs chmod -c 400 + +for SQUASHFS in *.squashfs; do + EXT4=$(basename $SQUASHFS .squashfs).ext4 + + # Create rw ext4 image from ro squashfs + [ -f $EXT4 ] && continue + say "Converting $SQUASHFS to $EXT4" + truncate -s 400M $EXT4 + unsquashfs $SQUASHFS + mkfs.ext4 -F $EXT4 -d squashfs-root + rm -rf squashfs-root +done From d6e324892fa1b407852c594dc89b18e723fd3e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Sep 2024 20:13:10 +0200 Subject: [PATCH 022/464] ci: build debug kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling ftrace in our kernels changed the performance of several tests, so it was reverted. Make a new set of kernels that will not be used for performance tests. While doing this, simplify our guest kernel config customization that relied on patches and use file concatenation instead. Turns out `make olddefconfig` produces the same result and we avoid the complexity of dealing with patches. Signed-off-by: Pablo Barbáchano --- resources/guest_configs/ci.config | 6 + resources/guest_configs/ftrace.config | 11 ++ ...g-options-for-what-is-needed-by-our-.patch | 98 --------------- ...-6.1-guest-kernel-configs-for-our-CI.patch | 76 ------------ .../patches/0003-enable-ftrace.patch | 115 ------------------ ...IG_ARM64_ERRATUM_3194386-for-aarch64.patch | 24 ---- resources/rebuild.sh | 29 ++--- tests/conftest.py | 12 ++ tests/framework/artifacts.py | 10 +- tools/sandbox.py | 11 ++ 10 files changed, 59 insertions(+), 333 deletions(-) create mode 100644 resources/guest_configs/ci.config create mode 100644 resources/guest_configs/ftrace.config delete mode 100644 resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch delete mode 100644 resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch delete mode 100644 resources/guest_configs/patches/0003-enable-ftrace.patch delete mode 100644 resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config new file mode 100644 index 00000000000..de77c73032c --- /dev/null +++ b/resources/guest_configs/ci.config @@ -0,0 +1,6 @@ +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_MSDOS_PARTITION=y +# aarch64 only TBD split into a separate file +CONFIG_DEVMEM=y +# CONFIG_ARM64_ERRATUM_3194386 is not set diff --git a/resources/guest_configs/ftrace.config b/resources/guest_configs/ftrace.config new file mode 100644 index 00000000000..b180c7f232a --- /dev/null +++ b/resources/guest_configs/ftrace.config @@ -0,0 +1,11 @@ +CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_TRACER=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPT_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_SYSCALLS=y diff --git a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch b/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch deleted file mode 100644 index ed1f683dce1..00000000000 --- a/resources/guest_configs/patches/0001-fix-Adjust-config-options-for-what-is-needed-by-our-.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 85e406b23c086c446ccfd6f8c83670800cc4de3a Mon Sep 17 00:00:00 2001 -From: Patrick Roy -Date: Tue, 30 Jul 2024 13:59:04 +0100 -Subject: [PATCH] fix: Adjust config options for what is needed by our tests - -Additionally, set `CONFIG_MSDOS_PARTITION=y` for our PARTUUID tests, -`CONFIG_DEVMEM=y` on aarch64/5.10 (for various integration tests that -rely on /dev/mem), and CONFIG_IKCONFIG=y and CONFIG_IKCONFIG_PROC=y for -the spectre-meltdown-checker.sh tests to work on AMD. - -Signed-off-by: Patrick Roy ---- - .../guest_configs/microvm-kernel-ci-aarch64-5.10.config | 7 ++++--- - .../microvm-kernel-ci-x86_64-5.10-no-acpi.config | 5 +++-- - .../guest_configs/microvm-kernel-ci-x86_64-5.10.config | 5 +++-- - 3 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c..0555055c 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -110,7 +110,8 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -752,7 +753,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -@@ -1726,7 +1727,7 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_HW_RANDOM_CCTRNG is not set - # CONFIG_HW_RANDOM_XIPHERA is not set - # CONFIG_HW_RANDOM_GRAVITON is not set --# CONFIG_DEVMEM is not set -+CONFIG_DEVMEM=y - # CONFIG_RAW_DRIVER is not set - # CONFIG_TCG_TPM is not set - # CONFIG_XILLYBUS is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -index b87fb3e4..a27c1f84 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -@@ -134,7 +134,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - - CONFIG_BUILD_BIN2C=y --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -702,7 +703,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -index 09461c17..af9ec662 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -@@ -127,7 +127,8 @@ CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - - CONFIG_BUILD_BIN2C=y --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -739,7 +740,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set --- -2.34.1 - diff --git a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch b/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch deleted file mode 100644 index 06604fd104a..00000000000 --- a/resources/guest_configs/patches/0002-ci-adjust-6.1-guest-kernel-configs-for-our-CI.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 911b916fdc53acfc7229302b029fd615f1e670cf Mon Sep 17 00:00:00 2001 -From: Babis Chalios -Date: Fri, 23 Aug 2024 12:54:26 +0200 -Subject: [PATCH 2/2] ci: adjust 6.1 guest kernel configs for our CI - -Set CONFIG_MSDOS_PARTITION=y for our PARTUUID tests, -CONFIG_DEVMEM=y on aarch64 for various integration tests that rely on -/dev/mem being there and CONFIG_IKCONFIG=y, CONFIG_IKCONFIG_PROC=y for -the spectre-meltdown-checker.sh tests to work on AMD. - -Signed-off-by: Babis Chalios ---- - .../guest_configs/microvm-kernel-ci-aarch64-6.1.config | 7 ++++--- - .../guest_configs/microvm-kernel-ci-x86_64-6.1.config | 7 ++++--- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a65..5c0334f4 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -140,7 +140,8 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y - # CONFIG_IKHEADERS is not set - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -@@ -753,7 +754,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set -@@ -1823,7 +1824,7 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_HW_RANDOM_XIPHERA is not set - CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=y - # CONFIG_HW_RANDOM_GRAVITON is not set --# CONFIG_DEVMEM is not set -+CONFIG_DEVMEM=y - # CONFIG_TCG_TPM is not set - # CONFIG_XILLYBUS is not set - CONFIG_RANDOM_TRUST_CPU=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -index 967e3203..8a2769c0 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -@@ -162,8 +162,9 @@ CONFIG_RCU_STALL_COMMON=y - CONFIG_RCU_NEED_SEGCBLIST=y - # end of RCU Subsystem - --# CONFIG_IKCONFIG is not set --# CONFIG_IKHEADERS is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+# CONFIG_IKHEADERS=y - CONFIG_LOG_BUF_SHIFT=17 - CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 - CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 -@@ -769,7 +770,7 @@ CONFIG_PARTITION_ADVANCED=y - # CONFIG_AMIGA_PARTITION is not set - # CONFIG_ATARI_PARTITION is not set - # CONFIG_MAC_PARTITION is not set --# CONFIG_MSDOS_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y - # CONFIG_LDM_PARTITION is not set - # CONFIG_SGI_PARTITION is not set - # CONFIG_ULTRIX_PARTITION is not set --- -2.34.1 - diff --git a/resources/guest_configs/patches/0003-enable-ftrace.patch b/resources/guest_configs/patches/0003-enable-ftrace.patch deleted file mode 100644 index a836a6fb3a7..00000000000 --- a/resources/guest_configs/patches/0003-enable-ftrace.patch +++ /dev/null @@ -1,115 +0,0 @@ -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c1..2a6f2310f 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -3089,7 +3089,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y - CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - # CONFIG_STRICT_DEVMEM is not set -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a658..f0f765298 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -3309,7 +3309,17 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y - CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - # CONFIG_STRICT_DEVMEM is not set - -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -index b87fb3e44..fc45dda19 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10-no-acpi.config -@@ -2905,7 +2905,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_FENTRY=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - CONFIG_STRICT_DEVMEM=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -index 09461c178..6d85bce2c 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-5.10.config -@@ -2987,7 +2987,17 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y - CONFIG_HAVE_FENTRY=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y - CONFIG_STRICT_DEVMEM=y -diff --git a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -index 967e32031..d11ef968a 100644 ---- a/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-x86_64-6.1.config -@@ -3185,7 +3185,17 @@ CONFIG_HAVE_OBJTOOL_MCOUNT=y - CONFIG_HAVE_C_RECORDMCOUNT=y - CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y - CONFIG_TRACING_SUPPORT=y --# CONFIG_FTRACE is not set -+CONFIG_FTRACE=y -+CONFIG_FUNCTION_TRACER=y -+CONFIG_FUNCTION_GRAPH_TRACER=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_PREEMPT_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+CONFIG_FTRACE_SYSCALLS=y - # CONFIG_SAMPLES is not set - CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y - CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y diff --git a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch b/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch deleted file mode 100644 index f3f16925e41..00000000000 --- a/resources/guest_configs/patches/0004-disable-CONFIG_ARM64_ERRATUM_3194386-for-aarch64.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -index ac44904c1..9f912a70b 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-5.10.config -@@ -341,6 +341,7 @@ CONFIG_ARM64_ERRATUM_1463225=y - CONFIG_ARM64_ERRATUM_1542419=y - CONFIG_ARM64_ERRATUM_1508412=y - CONFIG_ARM64_ERRATUM_2457168=y -+# CONFIG_ARM64_ERRATUM_3194386 is not set - CONFIG_CAVIUM_ERRATUM_22375=y - CONFIG_CAVIUM_ERRATUM_23144=y - CONFIG_CAVIUM_ERRATUM_23154=y -diff --git a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -index 26b87a658..29fe130f2 100644 ---- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -+++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config -@@ -362,6 +362,7 @@ CONFIG_ARM64_ERRATUM_2441009=y - CONFIG_ARM64_ERRATUM_2457168=y - CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y - CONFIG_ARM64_ERRATUM_2966298=y -+# CONFIG_ARM64_ERRATUM_3194386 is not set - CONFIG_CAVIUM_ERRATUM_22375=y - CONFIG_CAVIUM_ERRATUM_23144=y - CONFIG_CAVIUM_ERRATUM_23154=y diff --git a/resources/rebuild.sh b/resources/rebuild.sh index cff8a314cd7..69471afb3fa 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -134,12 +134,6 @@ function clone_amazon_linux_repo { [ -d linux ] || git clone https://github.com/amazonlinux/linux linux } -function apply_kernel_patches_for_ci { - for p in $PWD/guest_configs/patches/* ; do - patch -p2 < $p - done -} - # prints the git tag corresponding to the newest and best matching the provided kernel version $1 # this means that if a microvm kernel exists, the tag returned will be of the form # @@ -179,8 +173,9 @@ function build_al_kernel { echo "FATAL: Unsupported architecture!" exit 1 fi - cp "$KERNEL_CFG" .config - + # Concatenate all config files into one. olddefconfig will then resolve + # as needed. Later values override earlier ones. + cat "$@" >.config make olddefconfig make -j $(nproc) $target LATEST_VERSION=$(cat include/config/kernel.release) @@ -223,22 +218,24 @@ function build_al_kernels { clone_amazon_linux_repo - # Apply kernel patches on top of AL configuration - apply_kernel_patches_for_ci + CI_CONFIG="$PWD/guest_configs/ci.config" + FTRACE_CONFIG="$PWD/guest_configs/ftrace.config" if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config "$CI_CONFIG" fi if [[ $ARCH == "x86_64" && "$KERNEL_VERSION" == @(all|5.10-no-acpi) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10-no-acpi.config "$CI_CONFIG" fi if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then - build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config 5.10 + build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config "$CI_CONFIG" fi - # Undo kernel patches on top of AL configuration - git restore $PWD/guest_configs - rm -rf $PWD/guest_configs/*.orig + # Build debug kernels + OUTPUT_DIR=$OUTPUT_DIR/debug + mkdir -pv $OUTPUT_DIR + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config" "$CI_CONFIG" "$FTRACE_CONFIG" + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config" "$CI_CONFIG" "$FTRACE_CONFIG" } function print_help { diff --git a/tests/conftest.py b/tests/conftest.py index c77fee09039..1bb99fa859c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -432,6 +432,18 @@ def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_22): return microvm_factory.build(guest_kernel, rootfs_ubuntu_22) +guest_kernel_6_1_debug = pytest.fixture( + guest_kernel_fxt, + params=kernel_params("vmlinux-6.1*", artifact_dir=defs.ARTIFACT_DIR / "debug"), +) + + +@pytest.fixture +def uvm_plain_debug(microvm_factory, guest_kernel_6_1_debug, rootfs_rw): + """VM running a kernel with debug/trace Kconfig options""" + return microvm_factory.build(guest_kernel_6_1_debug, rootfs_rw) + + @pytest.fixture def uvm_with_initrd( microvm_factory, guest_kernel_linux_5_10, record_property, artifact_dir diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py index f4e05a88c94..77584f02129 100644 --- a/tests/framework/artifacts.py +++ b/tests/framework/artifacts.py @@ -32,12 +32,12 @@ def select_supported_kernels(): return supported_kernels -def kernels(glob) -> Iterator: +def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator: """Return supported kernels as kernels supported by the current combination of kernel and instance type. """ supported_kernels = select_supported_kernels() - for kernel in sorted(ARTIFACT_DIR.rglob(glob)): + for kernel in sorted(artifact_dir.glob(glob)): for kernel_regex in supported_kernels: if re.fullmatch(kernel_regex, kernel.name): yield kernel @@ -49,9 +49,11 @@ def disks(glob) -> Iterator: yield from sorted(ARTIFACT_DIR.glob(glob)) -def kernel_params(glob="vmlinux-*", select=kernels) -> Iterator: +def kernel_params( + glob="vmlinux-*", select=kernels, artifact_dir=ARTIFACT_DIR +) -> Iterator: """Return supported kernels""" - for kernel in select(glob): + for kernel in select(glob, artifact_dir): yield pytest.param(kernel, id=kernel.name) diff --git a/tools/sandbox.py b/tools/sandbox.py index fb15eb17fab..c8d5e488b59 100755 --- a/tools/sandbox.py +++ b/tools/sandbox.py @@ -73,6 +73,8 @@ def parse_byte_size(param): if args.cpu_template_path is not None: cpu_template = json.loads(args.cpu_template_path.read_text()) vmfcty = MicroVMFactory(*bins) + +print(f"uvm with kernel {args.kernel} ...") uvm = vmfcty.build(args.kernel, args.rootfs) uvm.help.enable_console() uvm.help.resize_disk(uvm.rootfs_file, args.rootfs_size) @@ -85,3 +87,12 @@ def parse_byte_size(param): print(cpu_template) uvm.start() uvm.get_all_metrics() + +kernel_dbg_dir = args.kernel.parent / "debug" +kernel_dbg = kernel_dbg_dir / args.kernel.name +print(f"uvm2 with kernel {kernel_dbg} ...") +uvm2 = vmfcty.build(kernel_dbg, args.rootfs) +uvm2.spawn() +uvm2.add_net_iface() +uvm2.basic_config(vcpu_count=args.vcpus, mem_size_mib=args.guest_mem_size // 2**20) +uvm2.start() From 31fceeece55335ae23fe57b211b239aed5938a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Sep 2024 09:24:22 +0200 Subject: [PATCH 023/464] ci: compress squashfs with zstd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compress squashfs with zstd since that now we have CONFIG_SQUASHFS_ZSTD=y in all our guest kernels. In my tests it is 78MB vs 85MB (an 8.2% reduction) Signed-off-by: Pablo Barbáchano --- resources/guest_configs/ci.config | 1 + resources/rebuild.sh | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config index de77c73032c..7bbf1fb1f56 100644 --- a/resources/guest_configs/ci.config +++ b/resources/guest_configs/ci.config @@ -1,6 +1,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_MSDOS_PARTITION=y +CONFIG_SQUASHFS_ZSTD=y # aarch64 only TBD split into a separate file CONFIG_DEVMEM=y # CONFIG_ARM64_ERRATUM_3194386 is not set diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 69471afb3fa..38bb0ecbf4a 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -79,10 +79,9 @@ EOF id_rsa=$OUTPUT_DIR/$ROOTFS_NAME.id_rsa cp id_rsa $id_rsa - # -comp zstd but guest kernel does not support rootfs_img="$OUTPUT_DIR/$ROOTFS_NAME.squashfs" mv $rootfs/root/manifest $OUTPUT_DIR/$ROOTFS_NAME.manifest - mksquashfs $rootfs $rootfs_img -all-root -noappend + mksquashfs $rootfs $rootfs_img -all-root -noappend -comp zstd rm -rf $rootfs for bin in fast_page_fault_helper fillmem init readmem; do rm $PWD/overlay/usr/local/bin/$bin From d7df5436f17ff6af8dfa8d5937d134868a8cddd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 17 Oct 2024 16:04:52 +0200 Subject: [PATCH 024/464] fix: workaround socat 1.8.0 bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit socat v1.8.0 in Ubuntu 24.04 has a bug when using `UDP-LISTEN` without specifying the address family. It looks like: E xioopen_ipdgram_listen(): unknown address family 0 We can work-around it by specifying IPv4. See http://www.dest-unreach.org/socat/CHANGES v1.8.0.1 Signed-off-by: Pablo Barbáchano --- tests/integration_tests/functional/test_net.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index e52389bc8b8..18d6f0da10a 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -99,7 +99,7 @@ def run_udp_offload_test(vm): # Start a UDP server in the guest # vm.ssh.check_output(f"nohup socat UDP-LISTEN:{port} - > {out_filename} &") vm.ssh.check_output( - f"nohup socat UDP-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &" + f"nohup socat UDP4-LISTEN:{port} OPEN:{out_filename},creat > /dev/null 2>&1 &" ) # Try to send a UDP message from host with UDP offload enabled From 50060ac8799691659ddd8f08aca7cf58f11771fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 20 Jun 2024 18:08:52 +0200 Subject: [PATCH 025/464] chore(rootfs): update rootfs to Ubuntu 24.04 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update guest rootfs to Ubuntu 24.04 Signed-off-by: Pablo Barbáchano --- README.md | 2 +- docs/getting-started.md | 18 ++++---- resources/rebuild.sh | 4 +- tests/README.md | 4 +- tests/conftest.py | 18 ++++---- tests/framework/utils_drive.py | 8 ++-- .../integration_tests/functional/test_api.py | 4 +- .../functional/test_cpu_features_aarch64.py | 12 +++--- .../functional/test_cpu_features_x86_64.py | 18 ++++---- .../functional/test_drive_vhost_user.py | 42 +++++++++---------- .../functional/test_drive_virtio.py | 4 +- .../functional/test_kernel_cmdline.py | 2 +- .../integration_tests/functional/test_net.py | 4 +- .../test_snapshot_not_losing_dirty_pages.py | 4 +- .../integration_tests/functional/test_uffd.py | 4 +- .../performance/test_huge_pages.py | 8 ++-- .../performance/test_vhost_user_metrics.py | 4 +- tests/integration_tests/security/test_nv.py | 4 +- .../security/test_vulnerabilities.py | 12 +++--- tools/create_snapshot_artifact/main.py | 4 +- 20 files changed, 89 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index dde5c21e794..f98079fc81c 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ We test all combinations of: | Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | | :-------- | :---------------- | :----------- | :----------- | -| c5n.metal | al2 linux_5.10 | ubuntu 22.04 | linux_5.10 | +| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | | m5n.metal | al2023 linux_6.1 | | linux_6.1 | | m6i.metal | | | | | m6a.metal | | | | diff --git a/docs/getting-started.md b/docs/getting-started.md index cb9a7fee9ee..46c2d09a872 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -9,7 +9,7 @@ You can check if your system meets the requirements by running `firecracker/tools/devtool checkenv`. An opinionated way to run Firecracker is to launch an -[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 22.04. +[EC2](https://aws.amazon.com/ec2/) `c5.metal` instance with Ubuntu 24.04. Firecracker requires [the KVM Linux kernel module](https://www.linux-kvm.org/) to perform its virtualization and emulation tasks. @@ -95,7 +95,7 @@ For simplicity, this guide will not use the [`jailer`](../src/jailer/). To successfully start a microVM, you will need an uncompressed Linux kernel binary, and an ext4 file system image (to use as rootfs). This guide uses a 5.10 -kernel image with a Ubuntu 22.04 rootfs from our CI: +kernel image with a Ubuntu 24.04 rootfs from our CI: ```bash ARCH="$(uname -m)" @@ -106,13 +106,13 @@ latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.1 wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" # Download a rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.ext4" +wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.ext4" # Download the ssh key for the rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-22.04.id_rsa" +wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.id_rsa" # Set user read permission on the ssh key -chmod 400 ./ubuntu-22.04.id_rsa +chmod 400 ./ubuntu-24.04.id_rsa ``` ### Getting a Firecracker Binary @@ -238,7 +238,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ }" \ "http://localhost/boot-source" -ROOTFS="./ubuntu-22.04.ext4" +ROOTFS="./ubuntu-24.04.ext4" # Set rootfs sudo curl -X PUT --unix-socket "${API_SOCKET}" \ @@ -280,13 +280,13 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ sleep 2s # Setup internet access in the guest -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" # Setup DNS resolution in the guest -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" # SSH into the microVM -ssh -i ./ubuntu-22.04.id_rsa root@172.16.0.2 +ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 # Use `root` for both the login and password. # Run `reboot` to exit. diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 38bb0ecbf4a..0d4b10c1dcd 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -48,7 +48,7 @@ function build_rootfs { cp -rvf overlay/* $rootfs - # curl -O https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz + # curl -O https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64-root.tar.xz # # TBD use systemd-nspawn instead of Docker # sudo tar xaf ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz -C $rootfs @@ -199,7 +199,7 @@ function prepare_and_build_rootfs { compile_and_install $BIN/devmemread.c $BIN/devmemread fi - build_rootfs ubuntu-22.04 jammy + build_rootfs ubuntu-24.04 noble build_initramfs } diff --git a/tests/README.md b/tests/README.md index 4fee1baee30..ea46ff56786 100644 --- a/tests/README.md +++ b/tests/README.md @@ -303,9 +303,9 @@ that are pre-initialized with specific guest kernels and rootfs: - `uvm_plain_any` is parametrized by the guest kernels [supported](../docs/kernel-policy.md) by Firecracker and a read-only Ubuntu - 22.04 squashfs as rootfs, + 24.04 squashfs as rootfs, - `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel - and the same Ubuntu 22.04 squashfs. + and the same Ubuntu 24.04 squashfs. Generally, tests should use the former if you are testing some interaction between the guest and Firecracker, while the latter should be used if diff --git a/tests/conftest.py b/tests/conftest.py index 1bb99fa859c..86869b9d229 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -383,26 +383,26 @@ def rootfs_fxt(request, record_property): # Fixtures for all Ubuntu rootfs, and specific versions rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("*.squashfs")) -rootfs_ubuntu_22 = pytest.fixture( - rootfs_fxt, params=rootfs_params("ubuntu-22*.squashfs") +rootfs_ubuntu_24 = pytest.fixture( + rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs") ) rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4")) @pytest.fixture -def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22): +def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24): """Create a vanilla VM, non-parametrized kernel: 5.10 - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + return microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) @pytest.fixture def uvm_plain_rw(microvm_factory, guest_kernel_linux_5_10, rootfs_rw): """Create a vanilla VM, non-parametrized kernel: 5.10 - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ return microvm_factory.build(guest_kernel_linux_5_10, rootfs_rw) @@ -424,12 +424,12 @@ def artifact_dir(): @pytest.fixture -def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_24): """All guest kernels kernel: all - rootfs: Ubuntu 22.04 + rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel, rootfs_ubuntu_22) + return microvm_factory.build(guest_kernel, rootfs_ubuntu_24) guest_kernel_6_1_debug = pytest.fixture( diff --git a/tests/framework/utils_drive.py b/tests/framework/utils_drive.py index 2e67ff41f39..7bb623d73e0 100644 --- a/tests/framework/utils_drive.py +++ b/tests/framework/utils_drive.py @@ -23,17 +23,15 @@ class VhostUserBlkBackendType(Enum): CROSVM = "Crosvm" -def partuuid_and_disk_path(rootfs_ubuntu_22, disk_path): +def partuuid_and_disk_path(rootfs, disk_path): """ We create a new file with specified path, get its partuuid and use it as a rootfs. """ - initial_size = rootfs_ubuntu_22.stat().st_size + 50 * MB + initial_size = rootfs.stat().st_size + 50 * MB disk_path.touch() os.truncate(disk_path, initial_size) check_output(f"echo type=83 | sfdisk --no-tell-kernel {str(disk_path)}", shell=True) - check_output( - f"dd bs=1M seek=1 if={str(rootfs_ubuntu_22)} of={disk_path}", shell=True - ) + check_output(f"dd bs=1M seek=1 if={str(rootfs)} of={disk_path}", shell=True) ptuuid = check_output( f"blkid -s PTUUID -o value {disk_path}", shell=True, encoding="ascii" ).strip() diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 5aebe7b5265..27366529c39 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -895,7 +895,7 @@ def _drive_patch(test_microvm): "is_root_device": True, "cache_type": "Unsafe", "is_read_only": True, - "path_on_host": "/ubuntu-22.04.squashfs", + "path_on_host": "/" + test_microvm.rootfs_file.name, "rate_limiter": None, "io_engine": "Sync", "socket": None, @@ -1226,7 +1226,7 @@ def test_get_full_config(uvm_plain): "is_root_device": True, "cache_type": "Unsafe", "is_read_only": True, - "path_on_host": "/ubuntu-22.04.squashfs", + "path_on_host": "/" + test_microvm.rootfs_file.name, "rate_limiter": None, "io_engine": "Sync", "socket": None, diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index fd04b17c305..1de1cad6f2e 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -148,12 +148,12 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): PLATFORM != "aarch64", reason="This is aarch64 specific test.", ) -def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) vm.spawn() vm.basic_config() vm.add_net_iface() @@ -167,13 +167,13 @@ def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_22): reason="This is aarch64 specific test.", ) def test_cpu_features_with_static_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template + microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) vm.spawn() vm.basic_config(cpu_template=cpu_template) vm.add_net_iface() @@ -195,13 +195,13 @@ def test_cpu_features_with_static_template( reason="This is aarch64 specific test.", ) def test_cpu_features_with_custom_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, custom_cpu_template + microvm_factory, guest_kernel, rootfs_ubuntu_24, custom_cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) vm.spawn() vm.basic_config() vm.api.cpu_config.put(**custom_cpu_template["template"]) 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 3174e9dda6c..f86a3972753 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -560,7 +560,7 @@ def msr_cpu_template_fxt(request): @pytest.mark.timeout(900) @pytest.mark.nonci def test_cpu_rdmsr( - microvm_factory, msr_cpu_template, guest_kernel, rootfs_ubuntu_22, results_dir + microvm_factory, msr_cpu_template, guest_kernel, rootfs_ubuntu_24, results_dir ): """ Test MSRs that are available to the guest. @@ -595,7 +595,7 @@ def test_cpu_rdmsr( """ vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -665,7 +665,7 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names): @pytest.mark.timeout(900) @pytest.mark.nonci def test_cpu_wrmsr_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template + microvm_factory, guest_kernel, rootfs_ubuntu_24, msr_cpu_template ): """ This is the first part of the test verifying @@ -686,7 +686,7 @@ def test_cpu_wrmsr_snapshot( shared_names = SNAPSHOT_RESTORE_SHARED_NAMES vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -822,7 +822,7 @@ def dump_cpuid_to_file(dump_fname, ssh_conn): @pytest.mark.timeout(900) @pytest.mark.nonci def test_cpu_cpuid_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_22, msr_cpu_template + microvm_factory, guest_kernel, rootfs_ubuntu_24, msr_cpu_template ): """ This is the first part of the test verifying @@ -839,7 +839,7 @@ def test_cpu_cpuid_snapshot( vm = microvm_factory.build( kernel=guest_kernel, - rootfs=rootfs_ubuntu_22, + rootfs=rootfs_ubuntu_24, ) vm.spawn() vm.add_net_iface() @@ -1215,9 +1215,9 @@ def check_enabled_features(test_microvm, cpu_template): "enhanced REP MOVSB/STOSB": "true", "SMAP: supervisor mode access prevention": "true", # xsave_0xd_0 - "XCR0 supported: x87 state": "true", - "XCR0 supported: SSE state": "true", - "XCR0 supported: AVX state": "true", + "x87 state": "true", + "SSE state": "true", + "AVX state": "true", # xsave_0xd_1 "XSAVEOPT instruction": "true", # extended_080000001_edx diff --git a/tests/integration_tests/functional/test_drive_vhost_user.py b/tests/integration_tests/functional/test_drive_vhost_user.py index 31a11a75661..1e3eaa1faeb 100644 --- a/tests/integration_tests/functional/test_drive_vhost_user.py +++ b/tests/integration_tests/functional/test_drive_vhost_user.py @@ -34,7 +34,7 @@ def _check_drives(test_microvm, assert_dict, keys_array): assert blockdev_out_line_cols[col] == assert_dict[key] -def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -44,12 +44,12 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True + "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True ) vm.add_net_iface() vhost_user_block_metrics = FcDeviceMetrics( @@ -67,7 +67,7 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22): vhost_user_block_metrics.validate(vm) -def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -78,14 +78,14 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_22, rootfs_rw) + shutil.copy(rootfs_ubuntu_24, rootfs_rw) vm.add_vhost_user_drive("rootfs", rootfs_rw, is_root_device=True) vm.add_net_iface() @@ -100,7 +100,7 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt _check_drives(vm, assert_dict, assert_dict.keys()) -def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ Test that even if backend is killed, Firecracker is still responsive. """ @@ -109,12 +109,12 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt # We need to set up ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True + "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True ) vm.add_net_iface() vm.start() @@ -127,7 +127,7 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt _config = vm.api.vm_config.get().json() -def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ Verify device ordering. @@ -139,7 +139,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -151,7 +151,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Adding second block device (rootfs) vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True + "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True ) # Adding third block device. @@ -160,7 +160,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_22, rootfs_rw) + shutil.copy(rootfs_ubuntu_24, rootfs_rw) # Adding forth block device. vm.add_vhost_user_drive("dummy_rootfs", rootfs_rw) @@ -171,7 +171,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): ) vm.start() - rootfs_size = rootfs_ubuntu_22.stat().st_size + rootfs_size = rootfs_ubuntu_24.stat().st_size # The devices were added in this order: fs1, rootfs, fs2. fs3 # However, the rootfs is the root device and goes first, @@ -203,7 +203,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_22): def test_partuuid_boot( microvm_factory, guest_kernel, - rootfs_ubuntu_22, + rootfs_ubuntu_24, ): """ Test the output reported by blockdev when booting with PARTUUID. @@ -213,14 +213,14 @@ def test_partuuid_boot( # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rootfs with partuuid unique to this microVM partuuid, disk_path = partuuid_and_disk_path( - rootfs_ubuntu_22, Path(vm.chroot()) / "disk.img" + rootfs_ubuntu_24, Path(vm.chroot()) / "disk.img" ) vm.add_vhost_user_drive( @@ -238,7 +238,7 @@ def test_partuuid_boot( _check_drives(vm, assert_dict, assert_dict.keys()) -def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ Test successful switching from PARTUUID boot to /dev/vda boot. """ @@ -247,7 +247,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa") + ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -256,7 +256,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Add the root block device specified through PARTUUID. vm.add_vhost_user_drive( "rootfs", - rootfs_ubuntu_22, + rootfs_ubuntu_24, is_root_device=True, partuuid="0eaa91a0-01", is_read_only=True, @@ -264,7 +264,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_22): # Adding a drive with the same ID creates another backend with another socket. vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_22, is_root_device=True, is_read_only=True + "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True ) vhost_user_block_metrics = FcDeviceMetrics( diff --git a/tests/integration_tests/functional/test_drive_virtio.py b/tests/integration_tests/functional/test_drive_virtio.py index dbebefa11a1..5dc24f65fb6 100644 --- a/tests/integration_tests/functional/test_drive_virtio.py +++ b/tests/integration_tests/functional/test_drive_virtio.py @@ -14,12 +14,12 @@ @pytest.fixture -def partuuid_and_disk_path_tmpfs(rootfs_ubuntu_22, tmp_path): +def partuuid_and_disk_path_tmpfs(rootfs_ubuntu_24, tmp_path): """ We create a new file in tmpfs, get its partuuid and use it as a rootfs. """ disk_path = tmp_path / "disk.img" - yield partuuid_and_disk_path(rootfs_ubuntu_22, disk_path) + yield partuuid_and_disk_path(rootfs_ubuntu_24, disk_path) disk_path.unlink() diff --git a/tests/integration_tests/functional/test_kernel_cmdline.py b/tests/integration_tests/functional/test_kernel_cmdline.py index 14e369790f1..9707eb8a92c 100644 --- a/tests/integration_tests/functional/test_kernel_cmdline.py +++ b/tests/integration_tests/functional/test_kernel_cmdline.py @@ -29,4 +29,4 @@ def test_init_params(uvm_plain): serial = Serial(vm) serial.open() # If the string does not show up, the test will fail. - serial.rx(token="Ubuntu 22.04") + serial.rx(token="Ubuntu 24.04") diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 18d6f0da10a..2d0b8b85cad 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -127,11 +127,11 @@ def test_tap_offload_booted(uvm_plain_any): run_udp_offload_test(vm) -def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs_ubuntu_22): +def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs_ubuntu_24): """ Verify that tap offload features are configured for a restored VM. """ - src = microvm_factory.build(guest_kernel, rootfs_ubuntu_22, monitor_memory=False) + src = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) src.spawn() src.basic_config() src.add_net_iface() diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py index 812e706b926..40eb45c742c 100644 --- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py +++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py @@ -25,14 +25,14 @@ def mount_tmpfs_small(worker_id): def test_diff_snapshot_works_after_error( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, mount_tmpfs_small + microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, mount_tmpfs_small ): """ Test that if a partial snapshot errors it will work after and not lose data """ uvm = microvm_factory.build( guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, jailer_kwargs={"chroot_base": mount_tmpfs_small}, ) diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index 44de52ed2d5..bc0a09dd288 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -14,10 +14,10 @@ @pytest.fixture(scope="function", name="snapshot") -def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22): +def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24): """Create a snapshot of a microVM.""" - basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) basevm.spawn() basevm.basic_config(vcpu_count=2, mem_size_mib=256) basevm.add_net_iface() diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 034ee6749a0..fa231353d39 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -70,14 +70,14 @@ def test_hugetlbfs_boot(uvm_plain): def test_hugetlbfs_snapshot( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, uffd_handler_paths + microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, uffd_handler_paths ): """ Test hugetlbfs snapshot restore via uffd """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=HugePagesConfig.HUGETLBFS_2MB, mem_size_mib=128) @@ -152,7 +152,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths) def test_ept_violation_count( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, uffd_handler_paths, metrics, huge_pages, @@ -163,7 +163,7 @@ def test_ept_violation_count( """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=huge_pages, mem_size_mib=256) diff --git a/tests/integration_tests/performance/test_vhost_user_metrics.py b/tests/integration_tests/performance/test_vhost_user_metrics.py index 45fb7a94114..905d14be882 100644 --- a/tests/integration_tests/performance/test_vhost_user_metrics.py +++ b/tests/integration_tests/performance/test_vhost_user_metrics.py @@ -11,7 +11,7 @@ @pytest.mark.parametrize("vcpu_count", [1, 2], ids=["1vcpu", "2vcpu"]) def test_vhost_user_block_metrics( - microvm_factory, guest_kernel_acpi, rootfs_ubuntu_22, vcpu_count, metrics + microvm_factory, guest_kernel_acpi, rootfs_ubuntu_24, vcpu_count, metrics ): """ This test tries to boot a VM with vhost-user-block @@ -29,7 +29,7 @@ def test_vhost_user_block_metrics( new_sizes = [20, 10, 30] # MB vm = microvm_factory.build( - guest_kernel_acpi, rootfs_ubuntu_22, monitor_memory=False + guest_kernel_acpi, rootfs_ubuntu_24, monitor_memory=False ) vm.spawn(log_level="Info") vm.basic_config(vcpu_count=vcpu_count) diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index ce848c6a789..7b264f6a6d5 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -21,10 +21,10 @@ @pytest.fixture def uvm_with_cpu_template( - microvm_factory, guest_kernel, rootfs_ubuntu_22, cpu_template_any + microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template_any ): """A microvm fixture parametrized with all possible templates""" - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_22) + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24) vm.spawn() cpu_template = None if isinstance(cpu_template_any, str): diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index d00aeb9d3c8..3eb910f5b65 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -67,13 +67,13 @@ def configure_microvm( def build_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, ): """Fixture returning a factory function for a normal microvm""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, firecracker=firecracker, jailer=jailer, ) @@ -81,13 +81,13 @@ def build_microvm( @pytest.fixture def build_microvm_with_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, cpu_template ): """Fixture returning a factory function for microvms with our built-in template""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, firecracker=firecracker, jailer=jailer, cpu_template=cpu_template, @@ -96,13 +96,13 @@ def build_microvm_with_template( @pytest.fixture def build_microvm_with_custom_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_22, custom_cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, custom_cpu_template ): """Fixture returning a factory function for microvms with custom cpu templates""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_22, + rootfs_ubuntu_24, firecracker=firecracker, jailer=jailer, custom_cpu_template=custom_cpu_template, diff --git a/tools/create_snapshot_artifact/main.py b/tools/create_snapshot_artifact/main.py index 75d439c1185..4a8ca35d6a6 100755 --- a/tools/create_snapshot_artifact/main.py +++ b/tools/create_snapshot_artifact/main.py @@ -78,8 +78,8 @@ def main(): | -> vm.mem -> vm.vmstate - -> ubuntu-22.04.id_rsa - -> ubuntu-22.04.ext4 + -> ubuntu-XX.YY.id_rsa + -> ubuntu-XX.YY.ext4 -> __guest_snapshot | ... From a69595f5f03757bd990318e7aa4f23409355ae13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 9 Oct 2024 11:23:43 +0200 Subject: [PATCH 026/464] ci: generate SSH key after downloading artifacts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generate SSH key after downloading artifacts, and add it to the rootfs. This avoids having an SSH key hardcoded in the rootfs. Downside is that we have to rebuild the rootfs, but that is fast. Signed-off-by: Pablo Barbáchano --- .buildkite/pipeline_cross.py | 3 +++ docs/getting-started.md | 16 +++++++++------- resources/rebuild.sh | 10 ---------- tools/setup-ci-artifacts.sh | 21 ++++++++++++++++++--- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index ceb89d27f3d..19b1d906b4d 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -21,6 +21,9 @@ instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"] instances_aarch64 = ["m7g.metal"] commands = [ + # we run 0 tests for the side effect of downloading the artifacts. We + # should convert create_snapshot_artifact to a proper test/ + "./tools/devtool test -- integration_tests/performance/test_benchmarks.py", "./tools/devtool -y sh ./tools/create_snapshot_artifact/main.py", "mkdir -pv snapshots/{instance}_{kv}", "sudo chown -Rc $USER: snapshot_artifacts", diff --git a/docs/getting-started.md b/docs/getting-started.md index 46c2d09a872..32ee0839d5d 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -106,13 +106,15 @@ latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.1 wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" # Download a rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.ext4" - -# Download the ssh key for the rootfs -wget "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.id_rsa" - -# Set user read permission on the ssh key -chmod 400 ./ubuntu-24.04.id_rsa +wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.squashfs" + +# Create an ssh key for the rootfs +unsquashfs ubuntu-24.04.squashfs.upstream +ssh-keygen -f id_rsa -N "" +cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys +mv -v id_rsa ./ubuntu-24.04.id_rsa +# re-squash +mksquashfs squashfs-root ubuntu-24.04.squashfs -all-root -noappend -comp zstd ``` ### Getting a Firecracker Binary diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 0d4b10c1dcd..c43ae480323 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -70,15 +70,6 @@ EOF # TBD what abt /etc/hosts? echo | tee $rootfs/etc/resolv.conf - # Generate key for ssh access from host - if [ ! -s id_rsa ]; then - ssh-keygen -f id_rsa -N "" - fi - install -d -m 0600 "$rootfs/root/.ssh/" - cp id_rsa.pub "$rootfs/root/.ssh/authorized_keys" - id_rsa=$OUTPUT_DIR/$ROOTFS_NAME.id_rsa - cp id_rsa $id_rsa - rootfs_img="$OUTPUT_DIR/$ROOTFS_NAME.squashfs" mv $rootfs/root/manifest $OUTPUT_DIR/$ROOTFS_NAME.manifest mksquashfs $rootfs $rootfs_img -all-root -noappend -comp zstd @@ -86,7 +77,6 @@ EOF for bin in fast_page_fault_helper fillmem init readmem; do rm $PWD/overlay/usr/local/bin/$bin done - rm -f id_rsa{,.pub} rm -f nohup.out } diff --git a/tools/setup-ci-artifacts.sh b/tools/setup-ci-artifacts.sh index 5829fdd6fe1..a0cfa40d1e3 100755 --- a/tools/setup-ci-artifacts.sh +++ b/tools/setup-ci-artifacts.sh @@ -14,17 +14,32 @@ cd build/img/$(uname -m) say "Fix executable permissions" find "firecracker" -type f |xargs chmod -c 755 -say "Fix RSA key permissions" -find . -type f -name "*.id_rsa" |xargs chmod -c 400 +say "Generate SSH key to connect from host" +if [ ! -s id_rsa ]; then + ssh-keygen -f id_rsa -N "" +fi for SQUASHFS in *.squashfs; do + say "Include SSH key in $SQUASHFS" + RSA=$(basename $SQUASHFS .squashfs).id_rsa EXT4=$(basename $SQUASHFS .squashfs).ext4 + [ -s $SQUASHFS.orig ] && continue + unsquashfs $SQUASHFS + mkdir -pv squashfs-root/root/.ssh + # copy the SSH key into the rootfs + if [ ! -s $RSA ]; then + # append SSH key to the squashfs image + cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys + cp -v id_rsa $RSA + fi + # re-squash + mv -v $SQUASHFS $SQUASHFS.orig + mksquashfs squashfs-root $SQUASHFS -all-root -noappend -comp zstd # Create rw ext4 image from ro squashfs [ -f $EXT4 ] && continue say "Converting $SQUASHFS to $EXT4" truncate -s 400M $EXT4 - unsquashfs $SQUASHFS mkfs.ext4 -F $EXT4 -d squashfs-root rm -rf squashfs-root done From 97e61ca9d561b00a233a4785233b0c431faa4c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 19 Jun 2024 20:30:56 +0200 Subject: [PATCH 027/464] tests: add Microvm.ssh.Popen command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This returns a Popen object instead of waiting for the command to finish. It may be useful when we need to incrementally read the output of a long running process in the guest, without having to use screen. Signed-off-by: Pablo Barbáchano --- tests/host_tools/network.py | 42 ++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index e1c53020fd0..7877b914d28 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -5,6 +5,7 @@ import ipaddress import random import string +import subprocess from dataclasses import dataclass, field from pathlib import Path @@ -67,9 +68,14 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): self._on_error = on_error + @property + def user_host(self): + """remote address for in SSH format @""" + return f"{self.user}@{self.host}" + def remote_path(self, path): """Convert a path to remote""" - return f"{self.user}@{self.host}:{path}" + return f"{self.user_host}:{path}" def _scp(self, path1, path2, options): """Copy files to/from the VM using scp.""" @@ -111,21 +117,12 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False): If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr. """ - command = [ - "ssh", - *self.options, - f"{self.user}@{self.host}", - cmd_string, - ] + command = ["ssh", *self.options, self.user_host, cmd_string] if debug: command.insert(1, "-vvv") - return self._exec( - command, - timeout, - check=check, - ) + return self._exec(command, timeout, check=check) def check_output(self, cmd_string, timeout=None, *, debug=False): """Same as `run`, but raises an exception on non-zero return code of remote command""" @@ -144,6 +141,27 @@ def _exec(self, cmd, timeout=None, check=False): raise + # pylint:disable=invalid-name + def Popen( + self, + cmd: str, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs, + ) -> subprocess.Popen: + """Execute the command in the guest and return a Popen object. + + pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done") + pop.stdout.read(16) + """ + cmd = ["ssh", *self.options, self.user_host, cmd] + if self.netns is not None: + cmd = ["ip", "netns", "exec", self.netns] + cmd + return subprocess.Popen( + cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs + ) + def mac_from_ip(ip_address): """Create a MAC address based on the provided IP. From 38a7951ca4f69c64b26f3f57b25f01ad1c5d2632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 16 Oct 2024 17:30:24 +0200 Subject: [PATCH 028/464] devctr: add trace-cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that we don't have to install it in the future. Signed-off-by: Pablo Barbáchano --- tools/devctr/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index eef52632a6a..e82f298b36b 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -83,7 +83,7 @@ RUN apt-get update \ # for crosvm (vhost-user-blk backend) libcap2 \ # for debugging - gdb strace \ + gdb strace trace-cmd \ && rm -rf /var/lib/apt/lists/* \ && pip3 install --upgrade poetry From 6c6118407db854e908946ee19242c176e0d8d17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 16 Oct 2024 17:41:24 +0200 Subject: [PATCH 029/464] tests: add a trace-cmd helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now it's a very simple one, but we can use it as a base to provide more complicated ones in the future. Signed-off-by: Pablo Barbáchano --- tests/framework/microvm_helpers.py | 23 +++++++++++++++++++++++ tools/sandbox.py | 4 +++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/framework/microvm_helpers.py b/tests/framework/microvm_helpers.py index 4239eb2489f..f29ae84a9a0 100644 --- a/tests/framework/microvm_helpers.py +++ b/tests/framework/microvm_helpers.py @@ -222,3 +222,26 @@ def run_in_netns(cmd): # add a route on the host for the clone address run(f"ip route add {ingress_ipv4} via {veth_guest_ip}") + + def trace_cmd_guest(self, fns, cmd, port=4321): + """Run trace-cmd on the guest, but transfer the data directly to the host.""" + docker_apt_install("trace-cmd") + print("host> trace-cmd listen") + _proc = subprocess.Popen( + [ + "ip", + "netns", + "exec", + self.vm.netns.id, + "trace-cmd", + "listen", + "-p", + str(port), + ] + ) + print("guest> trace-cmd record") + host_ip = self.vm.iface["eth0"]["iface"].host_ip + _guest_ps = self.vm.ssh.run( + f"trace-cmd record -N {host_ip}:{port} -p function {" ".join(fns)} {cmd}" + ) + return list(Path(".").glob("trace.*.dat")) diff --git a/tools/sandbox.py b/tools/sandbox.py index c8d5e488b59..3cdcec345a7 100755 --- a/tools/sandbox.py +++ b/tools/sandbox.py @@ -68,7 +68,6 @@ def parse_byte_size(param): else: bins = get_firecracker_binaries() -print("This step may take a while to compile Firecracker ...") cpu_template = None if args.cpu_template_path is not None: cpu_template = json.loads(args.cpu_template_path.read_text()) @@ -96,3 +95,6 @@ def parse_byte_size(param): uvm2.add_net_iface() uvm2.basic_config(vcpu_count=args.vcpus, mem_size_mib=args.guest_mem_size // 2**20) uvm2.start() +# trace-cmd needs this (DNS resolution?) +uvm2.help.enable_ip_forwarding() +files = uvm2.help.trace_cmd_guest(["-l", "read_msr"], cmd="sleep 5") From 5ec49b91660aa0a935e8e3376c75f0e5e9be9824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 17 Oct 2024 14:37:25 +0200 Subject: [PATCH 030/464] ci: use new CI rootfs 24.04 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new CI artifacts prepared for v1.11 Signed-off-by: Pablo Barbáchano --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 6cd9c95e9c4..00e453486e3 100755 --- a/tools/devtool +++ b/tools/devtool @@ -562,7 +562,7 @@ ensure_ci_artifacts() { # Fetch all the artifacts so they are local say "Fetching CI artifacts from S3" - S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.10/$(uname -m) + S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(uname -m) ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m) if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS From d420de50dfe7faba42d80ecf5754aefec1d2f745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 18 Oct 2024 12:59:40 +0200 Subject: [PATCH 031/464] ci: move create_snapshot_artifact to a test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's more hassle to keep this as a separate tool than including it in the tests, and we avoid having to treat it specially. Also this way we can run it in parallel easily. Signed-off-by: Pablo Barbáchano --- .buildkite/pipeline_cross.py | 10 +- docs/snapshotting/snapshot-support.md | 4 +- tests/conftest.py | 18 +- .../functional/test_snapshot_phase1.py | 108 ++++++++++++ tests/integration_tests/security/test_nv.py | 2 +- tools/create_snapshot_artifact/main.py | 163 ------------------ 6 files changed, 126 insertions(+), 179 deletions(-) create mode 100644 tests/integration_tests/functional/test_snapshot_phase1.py delete mode 100755 tools/create_snapshot_artifact/main.py diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index 19b1d906b4d..0e18d6e27c0 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -21,13 +21,9 @@ instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"] instances_aarch64 = ["m7g.metal"] commands = [ - # we run 0 tests for the side effect of downloading the artifacts. We - # should convert create_snapshot_artifact to a proper test/ - "./tools/devtool test -- integration_tests/performance/test_benchmarks.py", - "./tools/devtool -y sh ./tools/create_snapshot_artifact/main.py", + "./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py", "mkdir -pv snapshots/{instance}_{kv}", - "sudo chown -Rc $USER: snapshot_artifacts", - "mv -v snapshot_artifacts/* snapshots/{instance}_{kv}", + "mv -v test_results/test_snapshot_phase1/* snapshots/{instance}_{kv}", ] pipeline.build_group( "📸 create snapshots", @@ -86,7 +82,7 @@ f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}/* .", f"mv -v snapshots/{src_instance}_{src_kv} snapshot_artifacts", *pipeline.devtool_test( - pytest_opts=f"-m nonci {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", + pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", ), ], "label": f"🎬 {src_instance} {src_kv} ➡️ {dst_instance} {dst_kv}", diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index a9e0bc8dc4c..75ffd306e25 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -642,8 +642,8 @@ booting, to avoid this issue. We have a mechanism in place to experiment with snapshot compatibility across supported host kernel versions by generating snapshot artifacts through -[this tool](../../tools/create_snapshot_artifact) and checking devices' -functionality using +[this test](../../tests/integration_tests/functional/test_snapshot_phase1.py) +and checking devices' functionality using [this test](../../tests/integration_tests/functional/test_snapshot_restore_cross_kernel.py). The test restores the snapshot and ensures that all the devices set-up (network devices, disk, vsock, balloon and MMDS) are operational post-load. diff --git a/tests/conftest.py b/tests/conftest.py index 86869b9d229..27222bd0af2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -307,14 +307,20 @@ def custom_cpu_template(request, record_property): @pytest.fixture( - params=list(static_cpu_templates_params()) + list(custom_cpu_templates_params()) + params=[ + pytest.param(None, id="NO_CPU_TMPL"), + *static_cpu_templates_params(), + *custom_cpu_templates_params(), + ], ) def cpu_template_any(request, record_property): - """This fixture combines static and custom CPU templates""" - if "name" in request.param: - record_property("custom_cpu_template", request.param["name"]) - else: - record_property("static_cpu_template", request.param) + """This fixture combines no template, static and custom CPU templates""" + cpu_template_name = request.param + if request.param is None: + cpu_template_name = "None" + elif "name" in request.param: + cpu_template_name = request.param["name"] + record_property("cpu_template", cpu_template_name) return request.param diff --git a/tests/integration_tests/functional/test_snapshot_phase1.py b/tests/integration_tests/functional/test_snapshot_phase1.py new file mode 100644 index 00000000000..3c560b751e5 --- /dev/null +++ b/tests/integration_tests/functional/test_snapshot_phase1.py @@ -0,0 +1,108 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Creates snapshots for other tests like test_snapshot_restore_cross_kernel.py +""" + +import json +import platform +import re + +import pytest + +from framework.utils import ( + configure_mmds, + generate_mmds_get_request, + generate_mmds_session_token, +) + +if platform.machine() != "x86_64": + pytestmark = pytest.mark.skip("only x86_64 architecture supported") + +# Default IPv4 address to route MMDS requests. +IPV4_ADDRESS = "169.254.169.254" +NET_IFACE_FOR_MMDS = "eth3" + + +@pytest.mark.nonci +def test_snapshot_phase1( + microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template_any, results_dir +): + """Create a snapshot and save it to disk""" + + vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm.spawn(log_level="Info") + vm.add_net_iface() + + static_cpu_template = None + cpu_template_name = "None" + if isinstance(cpu_template_any, str): + static_cpu_template = cpu_template_any + cpu_template_name = f"static_{cpu_template_any}" + elif isinstance(cpu_template_any, dict): + vm.api.cpu_config.put(**cpu_template_any["template"]) + cpu_template_name = f"custom_{cpu_template_any['name']}" + vm.basic_config( + vcpu_count=2, + mem_size_mib=1024, + cpu_template=static_cpu_template, + ) + + guest_kernel_version = re.search("vmlinux-(.*)", vm.kernel_file.name) + snapshot_artifacts_dir = ( + results_dir + / f"{guest_kernel_version.group(1)}_{cpu_template_name}_guest_snapshot" + ) + + # Add 4 network devices + for i in range(4): + vm.add_net_iface() + # Add a vsock device + vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") + # Add MMDS + configure_mmds(vm, ["eth3"], version="V2") + # Add a memory balloon. + vm.api.balloon.put(amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1) + + vm.start() + + # Populate MMDS. + data_store = { + "latest": { + "meta-data": { + "ami-id": "ami-12345678", + "reservation-id": "r-fea54097", + "local-hostname": "ip-10-251-50-12.ec2.internal", + "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com", + } + } + } + + # MMDS should be empty. + assert vm.api.mmds.get().json() == {} + # Populate MMDS with data. + vm.api.mmds.put(**data_store) + # Ensure data is persistent inside the data store. + assert vm.api.mmds.get().json() == data_store + + # Iterate and validate connectivity on all ifaces after boot. + for i in range(4): + exit_code, _, _ = vm.ssh_iface(i).run("sync") + assert exit_code == 0 + + # Validate MMDS. + # Configure interface to route MMDS requests + vm.ssh.check_output(f"ip route add {IPV4_ADDRESS} dev {NET_IFACE_FOR_MMDS}") + + # Fetch metadata to ensure MMDS is accessible. + token = generate_mmds_session_token(vm.ssh, IPV4_ADDRESS, token_ttl=60) + cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token) + _, stdout, _ = vm.ssh.run(cmd) + assert json.loads(stdout) == data_store + + # Copy snapshot files to be published to S3 for the 2nd part of the test + # Create snapshot artifacts directory specific for the kernel version used. + snapshot = vm.snapshot_full() + snapshot_artifacts_dir.mkdir(parents=True) + snapshot.save_to(snapshot_artifacts_dir) diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index 7b264f6a6d5..66c5efaf4f5 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -30,7 +30,7 @@ def uvm_with_cpu_template( if isinstance(cpu_template_any, str): cpu_template = cpu_template_any vm.basic_config(cpu_template=cpu_template) - if cpu_template is None: + if isinstance(cpu_template_any, dict): vm.api.cpu_config.put(**cpu_template_any["template"]) vm.add_net_iface() vm.start() diff --git a/tools/create_snapshot_artifact/main.py b/tools/create_snapshot_artifact/main.py deleted file mode 100755 index 4a8ca35d6a6..00000000000 --- a/tools/create_snapshot_artifact/main.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Script used to generate snapshots of microVMs.""" - -import json -import os -import platform -import re -import shutil -import sys -from pathlib import Path - -# Hack to be able to import testing framework functions. -sys.path.append(os.path.join(os.getcwd(), "tests")) # noqa: E402 - -# pylint: disable=wrong-import-position -from framework.artifacts import disks, kernels -from framework.microvm import MicroVMFactory -from framework.utils import ( - configure_mmds, - generate_mmds_get_request, - generate_mmds_session_token, -) -from framework.utils_cpu_templates import get_supported_cpu_templates -from host_tools.cargo_build import get_firecracker_binaries - -# pylint: enable=wrong-import-position - -# Default IPv4 address to route MMDS requests. -IPV4_ADDRESS = "169.254.169.254" -NET_IFACE_FOR_MMDS = "eth3" -# Root directory for the snapshot artifacts. -SNAPSHOT_ARTIFACTS_ROOT_DIR = "snapshot_artifacts" - - -def populate_mmds(microvm, data_store): - """Populate MMDS contents with json data provided.""" - # MMDS should be empty. - response = microvm.api.mmds.get() - assert response.json() == {} - - # Populate MMDS with data. - microvm.api.mmds.put(**data_store) - - # Ensure data is persistent inside the data store. - response = microvm.api.mmds.get() - assert response.json() == data_store - - -def validate_mmds(ssh_connection, data_store): - """Validate that MMDS contents fetched from the guest.""" - # Configure interface to route MMDS requests - cmd = "ip route add {} dev {}".format(IPV4_ADDRESS, NET_IFACE_FOR_MMDS) - _, stdout, stderr = ssh_connection.run(cmd) - assert stdout == stderr == "" - - # Fetch metadata to ensure MMDS is accessible. - token = generate_mmds_session_token(ssh_connection, IPV4_ADDRESS, token_ttl=60) - - cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token) - _, stdout, _ = ssh_connection.run(cmd) - assert json.loads(stdout) == data_store - - -def main(): - """ - Run the main logic. - - Create snapshot artifacts from complex microVMs with all Firecracker's - functionality enabled. The kernels are parametrized to include all guest - supported versions. - - Artifacts are saved in the following format: - snapshot_artifacts - | - -> __guest_snapshot - | - -> vm.mem - -> vm.vmstate - -> ubuntu-XX.YY.id_rsa - -> ubuntu-XX.YY.ext4 - -> __guest_snapshot - | - ... - """ - # Create directory dedicated to store snapshot artifacts for - # each guest kernel version. - print("Cleanup") - shutil.rmtree(SNAPSHOT_ARTIFACTS_ROOT_DIR, ignore_errors=True) - vm_factory = MicroVMFactory(*get_firecracker_binaries()) - - cpu_templates = [] - if platform.machine() == "x86_64": - cpu_templates = ["None"] - cpu_templates += get_supported_cpu_templates() - - for cpu_template in cpu_templates: - for kernel in kernels(glob="vmlinux-*"): - for rootfs in disks(glob="ubuntu-*.squashfs"): - print(kernel, rootfs, cpu_template) - vm = vm_factory.build(kernel, rootfs) - vm.spawn(log_level="Info") - vm.basic_config( - vcpu_count=2, - mem_size_mib=1024, - cpu_template=cpu_template, - track_dirty_pages=True, - ) - # Add 4 network devices - for i in range(4): - vm.add_net_iface() - # Add a vsock device - vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") - # Add MMDS - configure_mmds(vm, ["eth3"], version="V2") - # Add a memory balloon. - vm.api.balloon.put( - amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1 - ) - - vm.start() - - # Populate MMDS. - data_store = { - "latest": { - "meta-data": { - "ami-id": "ami-12345678", - "reservation-id": "r-fea54097", - "local-hostname": "ip-10-251-50-12.ec2.internal", - "public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com", - } - } - } - populate_mmds(vm, data_store) - - # Iterate and validate connectivity on all ifaces after boot. - for i in range(4): - exit_code, _, _ = vm.ssh_iface(i).run("sync") - assert exit_code == 0 - - # Validate MMDS. - validate_mmds(vm.ssh, data_store) - - # Snapshot the microVM. - snapshot = vm.snapshot_diff() - - # Create snapshot artifacts directory specific for the kernel version used. - guest_kernel_version = re.search("vmlinux-(.*)", kernel.name) - - snapshot_artifacts_dir = ( - Path(SNAPSHOT_ARTIFACTS_ROOT_DIR) - / f"{guest_kernel_version.group(1)}_{cpu_template}_guest_snapshot" - ) - snapshot_artifacts_dir.mkdir(parents=True) - snapshot.save_to(snapshot_artifacts_dir) - print(f"Copied snapshot to: {snapshot_artifacts_dir}.") - - vm.kill() - - -if __name__ == "__main__": - main() From c20e42eccc2ad7f9689b09946209ab4cb8aabb81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 18 Oct 2024 16:01:13 +0200 Subject: [PATCH 032/464] ci: reduce storage of snapshots in cross-restore test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is so we use less IO overall sending snapshot to/from S3. - Punch holes in the memory snapshots - Decrease guest memory from 1GB to 512MB as it's not important to the test. This decreases around 10x: Before: 27GB * 22 runs ~ 594GB After: 2.7GB * 22 runs ~ 59.4GB Signed-off-by: Pablo Barbáchano --- .buildkite/pipeline_cross.py | 11 +++++++---- .../functional/test_snapshot_phase1.py | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index 0e18d6e27c0..d7cd261a3d0 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -22,8 +22,11 @@ instances_aarch64 = ["m7g.metal"] commands = [ "./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py", - "mkdir -pv snapshots/{instance}_{kv}", - "mv -v test_results/test_snapshot_phase1/* snapshots/{instance}_{kv}", + # punch holes in mem snapshot tiles and tar them so they are preserved in S3 + "find test_results/test_snapshot_phase1 -type f -name mem |xargs -P4 -t -n1 fallocate -d", + "mv -v test_results/test_snapshot_phase1 snapshot_artifacts", + "mkdir -pv snapshots", + "tar cSvf snapshots/{instance}_{kv}.tar snapshot_artifacts", ] pipeline.build_group( "📸 create snapshots", @@ -79,8 +82,8 @@ k_val = pytest_keyword_for_instance.get(dst_instance, "") step = { "command": [ - f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}/* .", - f"mv -v snapshots/{src_instance}_{src_kv} snapshot_artifacts", + f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}.tar .", + f"tar xSvf snapshots/{src_instance}_{src_kv}.tar", *pipeline.devtool_test( pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", ), diff --git a/tests/integration_tests/functional/test_snapshot_phase1.py b/tests/integration_tests/functional/test_snapshot_phase1.py index 3c560b751e5..ab52dfaad55 100644 --- a/tests/integration_tests/functional/test_snapshot_phase1.py +++ b/tests/integration_tests/functional/test_snapshot_phase1.py @@ -45,7 +45,7 @@ def test_snapshot_phase1( cpu_template_name = f"custom_{cpu_template_any['name']}" vm.basic_config( vcpu_count=2, - mem_size_mib=1024, + mem_size_mib=512, cpu_template=static_cpu_template, ) From 181619a4b0560c2e78df3443716bbc9ce230c7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 21 Oct 2024 18:22:53 +0200 Subject: [PATCH 033/464] doc: fix downloading kernel for ARM instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fix for when the patch kernel version is <100. Signed-off-by: Pablo Barbáchano --- docs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 32ee0839d5d..644d31e78a8 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -100,7 +100,7 @@ kernel image with a Ubuntu 24.04 rootfs from our CI: ```bash ARCH="$(uname -m)" -latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/x86_64/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep "(?<=)(firecracker-ci/v1.10/x86_64/vmlinux-5\.10\.[0-9]{3})(?=)" -o -P) +latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.10/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)") # Download a linux kernel binary wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" From 1bb4f4c63f1b9f39483fc61e150a589b6308750a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 23 Oct 2024 19:47:43 +0200 Subject: [PATCH 034/464] test: drop ubuntu version from rootfs fixture name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is unlikely that we will ever support more than one rootfs. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 13 ++--- .../functional/test_cpu_features_aarch64.py | 12 ++--- .../functional/test_cpu_features_x86_64.py | 16 +++--- .../functional/test_drive_vhost_user.py | 52 ++++++++----------- .../functional/test_drive_virtio.py | 4 +- .../integration_tests/functional/test_net.py | 4 +- .../test_snapshot_not_losing_dirty_pages.py | 4 +- .../functional/test_snapshot_phase1.py | 4 +- .../integration_tests/functional/test_uffd.py | 4 +- .../performance/test_huge_pages.py | 8 +-- .../performance/test_vhost_user_metrics.py | 6 +-- tests/integration_tests/security/test_nv.py | 6 +-- .../security/test_vulnerabilities.py | 12 ++--- 13 files changed, 62 insertions(+), 83 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 27222bd0af2..8f4c2e51ff5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -388,20 +388,17 @@ def rootfs_fxt(request, record_property): ) # Fixtures for all Ubuntu rootfs, and specific versions -rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("*.squashfs")) -rootfs_ubuntu_24 = pytest.fixture( - rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs") -) +rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs")) rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4")) @pytest.fixture -def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24): +def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs): """Create a vanilla VM, non-parametrized kernel: 5.10 rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) + return microvm_factory.build(guest_kernel_linux_5_10, rootfs) @pytest.fixture @@ -430,12 +427,12 @@ def artifact_dir(): @pytest.fixture -def uvm_plain_any(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def uvm_plain_any(microvm_factory, guest_kernel, rootfs): """All guest kernels kernel: all rootfs: Ubuntu 24.04 """ - return microvm_factory.build(guest_kernel, rootfs_ubuntu_24) + return microvm_factory.build(guest_kernel, rootfs) guest_kernel_6_1_debug = pytest.fixture( diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 1de1cad6f2e..8357f54b568 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -148,12 +148,12 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): PLATFORM != "aarch64", reason="This is aarch64 specific test.", ) -def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_default_cpu_features(microvm_factory, guest_kernel, rootfs): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config() vm.add_net_iface() @@ -167,13 +167,13 @@ def test_default_cpu_features(microvm_factory, guest_kernel, rootfs_ubuntu_24): reason="This is aarch64 specific test.", ) def test_cpu_features_with_static_template( - microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template + microvm_factory, guest_kernel, rootfs, cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config(cpu_template=cpu_template) vm.add_net_iface() @@ -195,13 +195,13 @@ def test_cpu_features_with_static_template( reason="This is aarch64 specific test.", ) def test_cpu_features_with_custom_template( - microvm_factory, guest_kernel, rootfs_ubuntu_24, custom_cpu_template + microvm_factory, guest_kernel, rootfs, custom_cpu_template ): """ Check the CPU features for a microvm with the specified config. """ - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.basic_config() vm.api.cpu_config.put(**custom_cpu_template["template"]) 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 f86a3972753..23818ddc6b1 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -560,7 +560,7 @@ def msr_cpu_template_fxt(request): @pytest.mark.timeout(900) @pytest.mark.nonci def test_cpu_rdmsr( - microvm_factory, msr_cpu_template, guest_kernel, rootfs_ubuntu_24, results_dir + microvm_factory, msr_cpu_template, guest_kernel, rootfs, results_dir ): """ Test MSRs that are available to the guest. @@ -595,7 +595,7 @@ def test_cpu_rdmsr( """ vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -664,9 +664,7 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names): ) @pytest.mark.timeout(900) @pytest.mark.nonci -def test_cpu_wrmsr_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_24, msr_cpu_template -): +def test_cpu_wrmsr_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template): """ This is the first part of the test verifying that MSRs retain their values after restoring from a snapshot. @@ -686,7 +684,7 @@ def test_cpu_wrmsr_snapshot( shared_names = SNAPSHOT_RESTORE_SHARED_NAMES vcpus, guest_mem_mib = 1, 1024 - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn() vm.add_net_iface() vm.basic_config( @@ -821,9 +819,7 @@ def dump_cpuid_to_file(dump_fname, ssh_conn): ) @pytest.mark.timeout(900) @pytest.mark.nonci -def test_cpu_cpuid_snapshot( - microvm_factory, guest_kernel, rootfs_ubuntu_24, msr_cpu_template -): +def test_cpu_cpuid_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_template): """ This is the first part of the test verifying that CPUID remains the same after restoring from a snapshot. @@ -839,7 +835,7 @@ def test_cpu_cpuid_snapshot( vm = microvm_factory.build( kernel=guest_kernel, - rootfs=rootfs_ubuntu_24, + rootfs=rootfs, ) vm.spawn() vm.add_net_iface() diff --git a/tests/integration_tests/functional/test_drive_vhost_user.py b/tests/integration_tests/functional/test_drive_vhost_user.py index 1e3eaa1faeb..79cc41b0f3a 100644 --- a/tests/integration_tests/functional/test_drive_vhost_user.py +++ b/tests/integration_tests/functional/test_drive_vhost_user.py @@ -34,7 +34,7 @@ def _check_drives(test_microvm, assert_dict, keys_array): assert blockdev_out_line_cols[col] == assert_dict[key] -def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_vhost_user_block(microvm_factory, guest_kernel, rootfs): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -44,13 +44,11 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_24): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vm.add_net_iface() vhost_user_block_metrics = FcDeviceMetrics( "vhost_user_block", 1, aggr_supported=False @@ -67,7 +65,7 @@ def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_24): vhost_user_block_metrics.validate(vm) -def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs): """ This test simply tries to boot a VM with vhost-user-block as a root device. @@ -78,14 +76,14 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_24, rootfs_rw) + shutil.copy(rootfs, rootfs_rw) vm.add_vhost_user_drive("rootfs", rootfs_rw, is_root_device=True) vm.add_net_iface() @@ -100,7 +98,7 @@ def test_vhost_user_block_read_write(microvm_factory, guest_kernel, rootfs_ubunt _check_drives(vm, assert_dict, assert_dict.keys()) -def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs): """ Test that even if backend is killed, Firecracker is still responsive. """ @@ -109,13 +107,11 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt # We need to set up ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vm.add_net_iface() vm.start() @@ -127,7 +123,7 @@ def test_vhost_user_block_disconnect(microvm_factory, guest_kernel, rootfs_ubunt _config = vm.api.vm_config.get().json() -def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_device_ordering(microvm_factory, guest_kernel, rootfs): """ Verify device ordering. @@ -139,7 +135,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -150,9 +146,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): vm.add_drive("scratch1", fs1.path) # Adding second block device (rootfs) - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) # Adding third block device. fs2 = drive_tools.FilesystemFile(os.path.join(vm.fsfiles, "scratch2"), size=512) @@ -160,7 +154,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): # Create a rw rootfs file that is unique to the microVM rootfs_rw = Path(vm.chroot()) / "rootfs" - shutil.copy(rootfs_ubuntu_24, rootfs_rw) + shutil.copy(rootfs, rootfs_rw) # Adding forth block device. vm.add_vhost_user_drive("dummy_rootfs", rootfs_rw) @@ -171,7 +165,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): ) vm.start() - rootfs_size = rootfs_ubuntu_24.stat().st_size + rootfs_size = rootfs.stat().st_size # The devices were added in this order: fs1, rootfs, fs2. fs3 # However, the rootfs is the root device and goes first, @@ -203,7 +197,7 @@ def test_device_ordering(microvm_factory, guest_kernel, rootfs_ubuntu_24): def test_partuuid_boot( microvm_factory, guest_kernel, - rootfs_ubuntu_24, + rootfs, ): """ Test the output reported by blockdev when booting with PARTUUID. @@ -213,15 +207,13 @@ def test_partuuid_boot( # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) # Create a rootfs with partuuid unique to this microVM - partuuid, disk_path = partuuid_and_disk_path( - rootfs_ubuntu_24, Path(vm.chroot()) / "disk.img" - ) + partuuid, disk_path = partuuid_and_disk_path(rootfs, Path(vm.chroot()) / "disk.img") vm.add_vhost_user_drive( "1", disk_path, is_root_device=True, partuuid=partuuid, is_read_only=True @@ -238,7 +230,7 @@ def test_partuuid_boot( _check_drives(vm, assert_dict, assert_dict.keys()) -def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_partuuid_update(microvm_factory, guest_kernel, rootfs): """ Test successful switching from PARTUUID boot to /dev/vda boot. """ @@ -247,7 +239,7 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_24): # We need to setup ssh keys manually because we did not specify rootfs # in microvm_factory.build method - ssh_key = rootfs_ubuntu_24.with_suffix(".id_rsa") + ssh_key = rootfs.with_suffix(".id_rsa") vm.ssh_key = ssh_key vm.spawn() vm.basic_config(add_root_device=False) @@ -256,16 +248,14 @@ def test_partuuid_update(microvm_factory, guest_kernel, rootfs_ubuntu_24): # Add the root block device specified through PARTUUID. vm.add_vhost_user_drive( "rootfs", - rootfs_ubuntu_24, + rootfs, is_root_device=True, partuuid="0eaa91a0-01", is_read_only=True, ) # Adding a drive with the same ID creates another backend with another socket. - vm.add_vhost_user_drive( - "rootfs", rootfs_ubuntu_24, is_root_device=True, is_read_only=True - ) + vm.add_vhost_user_drive("rootfs", rootfs, is_root_device=True, is_read_only=True) vhost_user_block_metrics = FcDeviceMetrics( "vhost_user_block", 1, aggr_supported=False diff --git a/tests/integration_tests/functional/test_drive_virtio.py b/tests/integration_tests/functional/test_drive_virtio.py index 5dc24f65fb6..9c61ead56a9 100644 --- a/tests/integration_tests/functional/test_drive_virtio.py +++ b/tests/integration_tests/functional/test_drive_virtio.py @@ -14,12 +14,12 @@ @pytest.fixture -def partuuid_and_disk_path_tmpfs(rootfs_ubuntu_24, tmp_path): +def partuuid_and_disk_path_tmpfs(rootfs, tmp_path): """ We create a new file in tmpfs, get its partuuid and use it as a rootfs. """ disk_path = tmp_path / "disk.img" - yield partuuid_and_disk_path(rootfs_ubuntu_24, disk_path) + yield partuuid_and_disk_path(rootfs, disk_path) disk_path.unlink() diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 2d0b8b85cad..a804b8f90a8 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -127,11 +127,11 @@ def test_tap_offload_booted(uvm_plain_any): run_udp_offload_test(vm) -def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs_ubuntu_24): +def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs): """ Verify that tap offload features are configured for a restored VM. """ - src = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) src.spawn() src.basic_config() src.add_net_iface() diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py index 40eb45c742c..5584cfceac8 100644 --- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py +++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py @@ -25,14 +25,14 @@ def mount_tmpfs_small(worker_id): def test_diff_snapshot_works_after_error( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, mount_tmpfs_small + microvm_factory, guest_kernel_linux_5_10, rootfs, mount_tmpfs_small ): """ Test that if a partial snapshot errors it will work after and not lose data """ uvm = microvm_factory.build( guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, jailer_kwargs={"chroot_base": mount_tmpfs_small}, ) diff --git a/tests/integration_tests/functional/test_snapshot_phase1.py b/tests/integration_tests/functional/test_snapshot_phase1.py index ab52dfaad55..7436c19d875 100644 --- a/tests/integration_tests/functional/test_snapshot_phase1.py +++ b/tests/integration_tests/functional/test_snapshot_phase1.py @@ -27,11 +27,11 @@ @pytest.mark.nonci def test_snapshot_phase1( - microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template_any, results_dir + microvm_factory, guest_kernel, rootfs, cpu_template_any, results_dir ): """Create a snapshot and save it to disk""" - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False) + vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) vm.spawn(log_level="Info") vm.add_net_iface() diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index bc0a09dd288..fbb86c4c987 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -14,10 +14,10 @@ @pytest.fixture(scope="function", name="snapshot") -def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24): +def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs): """Create a snapshot of a microVM.""" - basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) + basevm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) basevm.spawn() basevm.basic_config(vcpu_count=2, mem_size_mib=256) basevm.add_net_iface() diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index fa231353d39..8437d78c7d3 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -70,14 +70,14 @@ def test_hugetlbfs_boot(uvm_plain): def test_hugetlbfs_snapshot( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, uffd_handler_paths + microvm_factory, guest_kernel_linux_5_10, rootfs, uffd_handler_paths ): """ Test hugetlbfs snapshot restore via uffd """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=HugePagesConfig.HUGETLBFS_2MB, mem_size_mib=128) @@ -152,7 +152,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths) def test_ept_violation_count( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, uffd_handler_paths, metrics, huge_pages, @@ -163,7 +163,7 @@ def test_ept_violation_count( """ ### Create Snapshot ### - vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs_ubuntu_24) + vm = microvm_factory.build(guest_kernel_linux_5_10, rootfs) vm.memory_monitor = None vm.spawn() vm.basic_config(huge_pages=huge_pages, mem_size_mib=256) diff --git a/tests/integration_tests/performance/test_vhost_user_metrics.py b/tests/integration_tests/performance/test_vhost_user_metrics.py index 905d14be882..fd20b34a47b 100644 --- a/tests/integration_tests/performance/test_vhost_user_metrics.py +++ b/tests/integration_tests/performance/test_vhost_user_metrics.py @@ -11,7 +11,7 @@ @pytest.mark.parametrize("vcpu_count", [1, 2], ids=["1vcpu", "2vcpu"]) def test_vhost_user_block_metrics( - microvm_factory, guest_kernel_acpi, rootfs_ubuntu_24, vcpu_count, metrics + microvm_factory, guest_kernel_acpi, rootfs, vcpu_count, metrics ): """ This test tries to boot a VM with vhost-user-block @@ -28,9 +28,7 @@ def test_vhost_user_block_metrics( # low->high->low->high and so the numbers are not in monotonic sequence. new_sizes = [20, 10, 30] # MB - vm = microvm_factory.build( - guest_kernel_acpi, rootfs_ubuntu_24, monitor_memory=False - ) + vm = microvm_factory.build(guest_kernel_acpi, rootfs, monitor_memory=False) vm.spawn(log_level="Info") vm.basic_config(vcpu_count=vcpu_count) vm.add_net_iface() diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index 66c5efaf4f5..5dd5acb2308 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -20,11 +20,9 @@ @pytest.fixture -def uvm_with_cpu_template( - microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template_any -): +def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any): """A microvm fixture parametrized with all possible templates""" - vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24) + vm = microvm_factory.build(guest_kernel, rootfs) vm.spawn() cpu_template = None if isinstance(cpu_template_any, str): diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index 3eb910f5b65..fed9dbc96d7 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -67,13 +67,13 @@ def configure_microvm( def build_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, ): """Fixture returning a factory function for a normal microvm""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, firecracker=firecracker, jailer=jailer, ) @@ -81,13 +81,13 @@ def build_microvm( @pytest.fixture def build_microvm_with_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template ): """Fixture returning a factory function for microvms with our built-in template""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, firecracker=firecracker, jailer=jailer, cpu_template=cpu_template, @@ -96,13 +96,13 @@ def build_microvm_with_template( @pytest.fixture def build_microvm_with_custom_template( - microvm_factory, guest_kernel_linux_5_10, rootfs_ubuntu_24, custom_cpu_template + microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template ): """Fixture returning a factory function for microvms with custom cpu templates""" return lambda firecracker=None, jailer=None: configure_microvm( microvm_factory, guest_kernel_linux_5_10, - rootfs_ubuntu_24, + rootfs, firecracker=firecracker, jailer=jailer, custom_cpu_template=custom_cpu_template, From cf7dcc3033c12037c6120af30532b205b8435f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 29 Oct 2024 20:42:54 +0100 Subject: [PATCH 035/464] devctr: add zstd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stage it so next time we rebuild the devctr it's there, and we can use it to replace gzip, since it compresses better and faster. Signed-off-by: Pablo Barbáchano --- tools/devctr/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index e82f298b36b..de9b294345e 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -75,7 +75,7 @@ RUN apt-get update \ screen tmux \ tzdata \ tini \ - squashfs-tools \ + squashfs-tools zstd \ # for aws-lc-rs cmake \ # for Qemu vhost-user-blk backend From 761b4711b5c128a040f091560b4e2386f476abb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 29 Oct 2024 20:45:36 +0100 Subject: [PATCH 036/464] test: add debug information to debug kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add debugging information to debug kernels, but split it out by default. Signed-off-by: Pablo Barbáchano --- resources/guest_configs/debug.config | 5 +++++ resources/rebuild.sh | 27 ++++++++++++++++++++++++--- tools/setup-ci-artifacts.sh | 3 +++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 resources/guest_configs/debug.config diff --git a/resources/guest_configs/debug.config b/resources/guest_configs/debug.config new file mode 100644 index 00000000000..6ff73f2162b --- /dev/null +++ b/resources/guest_configs/debug.config @@ -0,0 +1,5 @@ +CONFIG_FRAME_POINTER=y +# CONFIG_KGDB=y +# CONFIG_KGDB_SERIAL_CONSOLE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF4=y diff --git a/resources/rebuild.sh b/resources/rebuild.sh index c43ae480323..90bac7addb7 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -193,6 +193,20 @@ function prepare_and_build_rootfs { build_initramfs } +function vmlinux_split_debuginfo { + VMLINUX="$1" + DEBUGINFO="$VMLINUX.debug" + VMLINUX_ORIG="$VMLINUX" + if [ $ARCH = "aarch64" ]; then + # in aarch64, the debug info is in vmlinux + VMLINUX_ORIG=linux/vmlinux + fi + objcopy --only-keep-debug $VMLINUX_ORIG $DEBUGINFO + objcopy --preserve-dates --strip-debug --add-gnu-debuglink=$DEBUGINFO $VMLINUX + # gdb does not support compressed files, but compress them because they are huge + gzip -v $DEBUGINFO +} + function build_al_kernels { if [[ $# = 0 ]]; then local KERNEL_VERSION="all" @@ -208,7 +222,6 @@ function build_al_kernels { clone_amazon_linux_repo CI_CONFIG="$PWD/guest_configs/ci.config" - FTRACE_CONFIG="$PWD/guest_configs/ftrace.config" if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then build_al_kernel $PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config "$CI_CONFIG" @@ -221,10 +234,18 @@ function build_al_kernels { fi # Build debug kernels + FTRACE_CONFIG="$PWD/guest_configs/ftrace.config" + DEBUG_CONFIG="$PWD/guest_configs/debug.config" OUTPUT_DIR=$OUTPUT_DIR/debug mkdir -pv $OUTPUT_DIR - build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config" "$CI_CONFIG" "$FTRACE_CONFIG" - build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config" "$CI_CONFIG" "$FTRACE_CONFIG" + if [[ "$KERNEL_VERSION" == @(all|5.10) ]]; then + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-5.10.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG" + vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-5.10.* + fi + if [[ "$KERNEL_VERSION" == @(all|6.1) ]]; then + build_al_kernel "$PWD/guest_configs/microvm-kernel-ci-$ARCH-6.1.config" "$CI_CONFIG" "$FTRACE_CONFIG" "$DEBUG_CONFIG" + vmlinux_split_debuginfo $OUTPUT_DIR/vmlinux-6.1.* + fi } function print_help { diff --git a/tools/setup-ci-artifacts.sh b/tools/setup-ci-artifacts.sh index a0cfa40d1e3..0d524658b51 100755 --- a/tools/setup-ci-artifacts.sh +++ b/tools/setup-ci-artifacts.sh @@ -43,3 +43,6 @@ for SQUASHFS in *.squashfs; do mkfs.ext4 -F $EXT4 -d squashfs-root rm -rf squashfs-root done + +say "Uncompress debuginfo files" +find . -name "*.debug.gz" -print0 | xargs -P4 -0 -t -n1 gunzip From e719d60cefee38f55f400c909830032eb9ef7529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 11:40:39 +0100 Subject: [PATCH 037/464] devctr: pin cargo-deny until we upgrade Rust version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cargo-deny raised its MSRV to 1.81.0 in 0.16.2, while we are still at 1.79.0. Pinning cargo-deny to last working version that works with our version of Rust. Signed-off-by: Pablo Barbáchano --- tools/devctr/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index de9b294345e..f0c7c36f759 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -107,7 +107,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && rustup target add x86_64-unknown-linux-musl \ && rustup target add aarch64-unknown-linux-musl \ && rustup component add llvm-tools-preview clippy rustfmt \ - && cargo install --locked cargo-audit cargo-deny grcov cargo-sort cargo-afl \ + && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \ && cargo install --locked kani-verifier && cargo kani setup \ \ && apt-get update \ From 9184e8264833ffe6e8e7c8ab8e0980af6b14d59e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:05:50 +0000 Subject: [PATCH 038/464] build(deps): Bump the firecracker group with 13 updates Bumps the firecracker group with 13 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.9` | `0.8.10` | | [clap](https://github.com/clap-rs/clap) | `4.5.20` | `4.5.21` | | [libc](https://github.com/rust-lang/libc) | `0.2.162` | `0.2.164` | | [serde](https://github.com/serde-rs/serde) | `1.0.214` | `1.0.215` | | [serde_json](https://github.com/serde-rs/json) | `1.0.132` | `1.0.133` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.214` | `1.0.215` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.10.0` | `1.11.0` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.12.13` | `0.12.14` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.22.0` | `0.23.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.1.37` | `1.2.1` | | [clap_builder](https://github.com/clap-rs/clap) | `4.5.20` | `4.5.21` | | [clap_lex](https://github.com/clap-rs/clap) | `0.7.2` | `0.7.3` | | [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.14` | `0.2.15` | Updates `zerocopy` from 0.8.9 to 0.8.10 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.9...v0.8.10) Updates `clap` from 4.5.20 to 4.5.21 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.20...clap_complete-v4.5.21) Updates `libc` from 0.2.162 to 0.2.164 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.162...0.2.164) Updates `serde` from 1.0.214 to 1.0.215 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.214...v1.0.215) Updates `serde_json` from 1.0.132 to 1.0.133 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.132...v1.0.133) Updates `serde_derive` from 1.0.214 to 1.0.215 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.214...v1.0.215) Updates `aws-lc-rs` from 1.10.0 to 1.11.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.10.0...v1.11.0) Updates `aws-lc-fips-sys` from 0.12.13 to 0.12.14 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.12.13...aws-lc-fips-sys/v0.12.14) Updates `aws-lc-sys` from 0.22.0 to 0.23.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.22.0...aws-lc-sys/v0.23.0) Updates `cc` from 1.1.37 to 1.2.1 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.37...cc-v1.2.1) Updates `clap_builder` from 4.5.20 to 4.5.21 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.20...v4.5.21) Updates `clap_lex` from 0.7.2 to 0.7.3 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.2...clap_lex-v0.7.3) Updates `cpufeatures` from 0.2.14 to 0.2.15 - [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.14...cpufeatures-v0.2.15) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_lex dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cpufeatures dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 70 +++++++++++++++--------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 8 ++-- src/firecracker/Cargo.toml | 14 +++--- src/jailer/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 6 +-- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 6 +-- src/vmm/Cargo.toml | 10 ++--- 11 files changed, 63 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe779e26d13..b3ad7e16b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.3", "vm-memory", - "zerocopy 0.8.9", + "zerocopy 0.8.10", ] [[package]] @@ -125,11 +125,11 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.12.13" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf12b67bc9c5168f68655aadb2a12081689a58f1d9b1484705e4d1810ed6e4ac" +checksum = "8671005a9c1e80bd3dc9aee84c5bfd594d32a3d645fdb56d5d9d5e26daa4c315" dependencies = [ - "bindgen 0.69.4", + "bindgen 0.69.5", "cc", "cmake", "dunce", @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -154,11 +154,11 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96" dependencies = [ - "bindgen 0.69.4", + "bindgen 0.69.5", "cc", "cmake", "dunce", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags 2.6.0", "cexpr", @@ -261,9 +261,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.37" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -360,9 +360,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clippy-tracing" @@ -433,9 +433,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -857,9 +857,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libloading" @@ -1239,18 +1239,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -1259,9 +1259,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1630,7 +1630,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.9", + "zerocopy 0.8.10", ] [[package]] @@ -1807,11 +1807,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49e690f8f352f4a9ee8679a8c5921f42ffd0d6d6413a0a66b8e81cf524e109c" +checksum = "a13a42ed30c63171d820889b2981318736915150575b8d2d6dbee7edd68336ca" dependencies = [ - "zerocopy-derive 0.8.9", + "zerocopy-derive 0.8.10", ] [[package]] @@ -1827,9 +1827,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa732fcc881df7a6fbe8e3ed17baadece53b379ad58fe2633396b1a2b108a7b1" +checksum = "593e7c96176495043fcb9e87cf7659f4d18679b5bab6b92bdef359c76a7795dd" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 5932faa732b..15137400180 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.3" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.9", features = ["derive"] } +zerocopy = { version = "0.8.10", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 4dcd08e42eb..91e03a2afb8 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.20", features = ["derive"] } +clap = { version = "4.5.21", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.89", features = ["span-locations"] } quote = "1.0.37" diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 365945b6198..6654bb090c4 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,12 +10,12 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.20", features = ["derive", "string"] } +clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.214", features = ["derive"] } -serde_json = "1.0.132" +serde = { version = "1.0.215", features = ["derive"] } +serde_json = "1.0.133" thiserror = "2.0.3" vmm = { path = "../vmm" } diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 39153386379..8d0889c23dd 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,14 +18,14 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.132" +serde_json = "1.0.133" thiserror = "2.0.3" timerfd = "1.6.0" utils = { path = "../utils" } @@ -34,18 +34,18 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.20.5" -libc = "0.2.162" +libc = "0.2.164" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] bincode = "1.2.1" seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.214" } -serde_json = "1.0.132" +serde = { version = "1.0.215" } +serde_json = "1.0.133" [features] tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 95dc953ae77..55b50efb785 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,7 +12,7 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 1a0dab4c2a8..c944f5f346d 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } thiserror = "2.0.3" vmm-sys-util = "0.12.1" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 91a556d8996..1916a085b51 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,10 +18,10 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.214", features = ["derive"] } -serde_json = "1.0.132" +serde = { version = "1.0.215", features = ["derive"] } +serde_json = "1.0.133" thiserror = "2.0.3" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index af59a6c5e03..022342d896f 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,11 +10,11 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.20", features = ["derive", "string"] } +clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" thiserror = "2.0.3" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index bc792ac5801..2514ee05b0b 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,15 +11,15 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.162" +libc = "0.2.164" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.3" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vmm-sys-util = "0.12.1" [dev-dependencies] -serde_json = "1.0.132" +serde_json = "1.0.133" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 2115b0e7253..070cae5088f 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.10.0", features = ["bindgen"] } +aws-lc-rs = { version = "1.11.0", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.6.0" @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.162" +libc = "0.2.164" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -34,8 +34,8 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } semver = { version = "1.0.23", features = ["serde"] } -serde = { version = "1.0.214", features = ["derive", "rc"] } -serde_json = "1.0.132" +serde = { version = "1.0.215", features = ["derive", "rc"] } +serde_json = "1.0.133" slab = "0.4.7" thiserror = "2.0.3" timerfd = "1.5.0" @@ -46,7 +46,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.9" } +zerocopy = { version = "0.8.10" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 350d6179e7b8e8d4306900f12c9577a082835ba2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:34:39 +0000 Subject: [PATCH 039/464] build(deps): Bump aiohttp from 3.10.5 to 3.10.11 in /tools/devctr Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.5 to 3.10.11. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.5...v3.10.11) --- updated-dependencies: - dependency-name: aiohttp dependency-type: indirect ... Signed-off-by: dependabot[bot] --- tools/devctr/poetry.lock | 476 +++++++++++++++++++++++---------------- 1 file changed, 287 insertions(+), 189 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index fef3e284ade..96f1d0c990a 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -13,112 +13,112 @@ files = [ [[package]] name = "aiohttp" -version = "3.10.5" +version = "3.10.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"}, - {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"}, - {file = "aiohttp-3.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683"}, - {file = "aiohttp-3.10.5-cp310-cp310-win32.whl", hash = "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef"}, - {file = "aiohttp-3.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058"}, - {file = "aiohttp-3.10.5-cp311-cp311-win32.whl", hash = "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072"}, - {file = "aiohttp-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6"}, - {file = "aiohttp-3.10.5-cp312-cp312-win32.whl", hash = "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12"}, - {file = "aiohttp-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987"}, - {file = "aiohttp-3.10.5-cp313-cp313-win32.whl", hash = "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04"}, - {file = "aiohttp-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511"}, - {file = "aiohttp-3.10.5-cp38-cp38-win32.whl", hash = "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a"}, - {file = "aiohttp-3.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11"}, - {file = "aiohttp-3.10.5-cp39-cp39-win32.whl", hash = "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1"}, - {file = "aiohttp-3.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862"}, - {file = "aiohttp-3.10.5.tar.gz", hash = "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, + {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, + {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, + {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, + {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, + {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, + {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, + {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, + {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, + {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, + {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, + {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, + {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, + {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, ] [package.dependencies] aiohappyeyeballs = ">=2.3.0" aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" +yarl = ">=1.12.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] @@ -1317,6 +1317,113 @@ files = [ [package.dependencies] wcwidth = "*" +[[package]] +name = "propcache" +version = "0.2.0" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.8" +files = [ + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, + {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, + {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, + {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, + {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, + {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, + {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, + {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, + {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, + {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, + {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, + {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, + {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, + {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, + {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, +] + [[package]] name = "psutil" version = "6.0.0" @@ -2155,108 +2262,99 @@ files = [ [[package]] name = "yarl" -version = "1.11.1" +version = "1.17.2" description = "Yet another URL library" optional = false -python-versions = ">=3.8" -files = [ - {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00"}, - {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d"}, - {file = "yarl-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e"}, - {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc"}, - {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec"}, - {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf"}, - {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49"}, - {file = "yarl-1.11.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff"}, - {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad"}, - {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145"}, - {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd"}, - {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26"}, - {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46"}, - {file = "yarl-1.11.1-cp310-cp310-win32.whl", hash = "sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91"}, - {file = "yarl-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998"}, - {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68"}, - {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe"}, - {file = "yarl-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675"}, - {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63"}, - {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27"}, - {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5"}, - {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92"}, - {file = "yarl-1.11.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b"}, - {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a"}, - {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83"}, - {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff"}, - {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c"}, - {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e"}, - {file = "yarl-1.11.1-cp311-cp311-win32.whl", hash = "sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6"}, - {file = "yarl-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b"}, - {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0"}, - {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265"}, - {file = "yarl-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867"}, - {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd"}, - {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef"}, - {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8"}, - {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870"}, - {file = "yarl-1.11.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2"}, - {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84"}, - {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa"}, - {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff"}, - {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239"}, - {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45"}, - {file = "yarl-1.11.1-cp312-cp312-win32.whl", hash = "sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447"}, - {file = "yarl-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639"}, - {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c"}, - {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e"}, - {file = "yarl-1.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93"}, - {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d"}, - {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7"}, - {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089"}, - {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5"}, - {file = "yarl-1.11.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5"}, - {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786"}, - {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318"}, - {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82"}, - {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a"}, - {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da"}, - {file = "yarl-1.11.1-cp313-cp313-win32.whl", hash = "sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979"}, - {file = "yarl-1.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367"}, - {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4"}, - {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b"}, - {file = "yarl-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc"}, - {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937"}, - {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b"}, - {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591"}, - {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e"}, - {file = "yarl-1.11.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05"}, - {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f"}, - {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413"}, - {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7"}, - {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14"}, - {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420"}, - {file = "yarl-1.11.1-cp38-cp38-win32.whl", hash = "sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a"}, - {file = "yarl-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6"}, - {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269"}, - {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26"}, - {file = "yarl-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909"}, - {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4"}, - {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a"}, - {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804"}, - {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79"}, - {file = "yarl-1.11.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520"}, - {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366"}, - {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c"}, - {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e"}, - {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9"}, - {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df"}, - {file = "yarl-1.11.1-cp39-cp39-win32.whl", hash = "sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74"}, - {file = "yarl-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0"}, - {file = "yarl-1.11.1-py3-none-any.whl", hash = "sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38"}, - {file = "yarl-1.11.1.tar.gz", hash = "sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53"}, +python-versions = ">=3.9" +files = [ + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"}, + {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"}, + {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"}, + {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"}, + {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"}, + {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"}, + {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"}, + {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"}, + {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"}, + {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"}, + {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"}, + {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"}, + {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"}, ] [package.dependencies] idna = ">=2.0" multidict = ">=4.0" +propcache = ">=0.2.0" [metadata] lock-version = "2.0" From 5487c063c47ef98ffb8ebe2ae5e867530b1bea1e Mon Sep 17 00:00:00 2001 From: Matthew Buckingham-Bishop Date: Mon, 11 Nov 2024 14:20:02 +0000 Subject: [PATCH 040/464] fix: devtool install --path broken ensures binaries are installed in the directory specified by --path. previously binaries could be overwriten during installation. Signed-off-by: Matthew Buckingham-Bishop --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 00e453486e3..c3b7b27ed98 100755 --- a/tools/devtool +++ b/tools/devtool @@ -1191,7 +1191,7 @@ cmd_install() { # Install the binaries for binary in "${binaries[@]}"; do say "Installing $binary in $install_path" - install -m 755 "$( build_bin_path "$target" "$profile" "$binary" )" "$install_path" + install -m 755 -D -t "$install_path" "$( build_bin_path "$target" "$profile" "$binary" )" done } From a1016284092c51fb3b5d8fb71bfee345e61ef213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 20 Nov 2024 13:35:36 +0100 Subject: [PATCH 041/464] ci: infer instance architecture from a heuristic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps the script work for instances it doesn't know about, which is helpful while onboarding new instances. Only Graviton metal instances are aarch64 at the moment. Fixes: c33bc6c6f32a886cf186d4c4130cb0f6bd66bdca Signed-off-by: Pablo Barbáchano --- .buildkite/common.py | 27 ++++++++++++++++----------- .buildkite/pipeline_cpu_template.py | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index 196435bb2e0..a8913d5d6ef 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -13,14 +13,14 @@ import subprocess from pathlib import Path -DEFAULT_INSTANCES = { - "c5n.metal": "x86_64", # Intel Skylake - "m5n.metal": "x86_64", # Intel Cascade Lake - "m6i.metal": "x86_64", # Intel Icelake - "m6a.metal": "x86_64", # AMD Milan - "m6g.metal": "aarch64", # Graviton2 - "m7g.metal": "aarch64", # Graviton3 -} +DEFAULT_INSTANCES = [ + "c5n.metal", # Intel Skylake + "m5n.metal", # Intel Cascade Lake + "m6i.metal", # Intel Icelake + "m6a.metal", # AMD Milan + "m6g.metal", # Graviton2 + "m7g.metal", # Graviton3 +] DEFAULT_PLATFORMS = [ ("al2", "linux_5.10"), @@ -28,6 +28,11 @@ ] +def get_arch_for_instance(instance): + """Return instance architecture""" + return "x86_64" if instance[2] != "g" else "aarch64" + + def overlay_dict(base: dict, update: dict): """Overlay a dict over a base one""" base = base.copy() @@ -145,7 +150,7 @@ def __call__(self, parser, namespace, value, option_string=None): "--instances", required=False, nargs="+", - default=DEFAULT_INSTANCES.keys(), + default=DEFAULT_INSTANCES, ) COMMON_PARSER.add_argument( "--platforms", @@ -288,7 +293,7 @@ def _adapt_group(self, group): step["command"] = prepend + step["command"] if self.shared_build is not None: step["depends_on"] = self.build_key( - DEFAULT_INSTANCES[step["agents"]["instance"]] + get_arch_for_instance(step["agents"]["instance"]) ) return group @@ -323,7 +328,7 @@ def build_group_per_arch(self, label, *args, **kwargs): if set_key: for step in grp["steps"]: step["key"] = self.build_key( - DEFAULT_INSTANCES[step["agents"]["instance"]] + get_arch_for_instance(step["agents"]["instance"]) ) return self.add_step(grp, depends_on_build=depends_on_build) diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py index 72a67ea5e7d..c8c5f75fa09 100755 --- a/.buildkite/pipeline_cpu_template.py +++ b/.buildkite/pipeline_cpu_template.py @@ -34,7 +34,7 @@ class BkStep(str, Enum): "tools/devtool -y test --no-build -- -m no_block_pr integration_tests/functional/test_cpu_template_helper.py -k test_guest_cpu_config_change", ], BkStep.LABEL: "🖐️ fingerprint", - "instances": DEFAULT_INSTANCES.keys(), + "instances": DEFAULT_INSTANCES, "platforms": DEFAULT_PLATFORMS, }, "cpuid_wrmsr": { From f2ef491e0851db996cee49c4e3f7ad7c01bb3e68 Mon Sep 17 00:00:00 2001 From: kanpov Date: Wed, 20 Nov 2024 20:10:45 +0300 Subject: [PATCH 042/464] Improve network-setup with nft support and further instructions - Support for multiple guests - Kernel network configuration using boot arg Signed-off-by: kanpov --- docs/network-setup.md | 358 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 292 insertions(+), 66 deletions(-) diff --git a/docs/network-setup.md b/docs/network-setup.md index ad77bd3e7e9..fb2c1ca0977 100644 --- a/docs/network-setup.md +++ b/docs/network-setup.md @@ -1,49 +1,108 @@ # Getting Started Firecracker Network Setup -This is a very simple quick-start guide to getting a Firecracker guest connected -to the network. If you're using Firecracker in production, or even want to run -multiple guests, you'll need to adapt this setup. +This is a simple quick-start guide to getting one or more Firecracker microVMs +connected to the Internet via the host. If you run a production setup, you +should consider modifying this setup to accommodate your specific needs. -**Note** Currently firecracker supports only TUN/TAP network backend with no +**Note:** Currently, Firecracker supports only a TUN/TAP network backend with no multi queue support. -The simple steps in this guide assume that your internet-facing interface is -`eth0`, you have nothing else using `tap0` and no other `iptables` rules. Check -out the *Advanced:* sections if that doesn't work for you. +The steps in this guide assume `eth0` to be your Internet-facing network +interface on the host. If `eth0` isn't your main network interface, you should +change the value to the correct one in the commands below. IPv4 is also assumed +to be used, so you will need to adapt the instructions accordingly to support +IPv6. + +Each microVM requires a host network interface (like `eth0`) and a Linux `tap` +device (like `tap0`) used by Firecracker, but the differences in configuration +stem from routing: how packets from the `tap` get to the network interface +(egress) and vice-versa (ingress). There are three main approaches of how to +configure routing for a microVM. + +1. **NAT-based**, which is presented in the main part of this guide. It is + simple but doesn't expose your microVM to the local network (LAN). +1. **Bridge-based**, which exposes your microVM to the local network. Learn more + about in the _Advanced: Bridge-based routing_ section of this guide. +1. **Namespaced NAT**, which sacrifices performance in comparison to the other + approaches but is desired in the scenario when two clones of the same microVM + are running at the same time. To learn more about it, check out the + [Network Connectivity for Clones](./snapshotting/network-for-clones.md) + guide. + +To run multiple microVMs while using NAT-based routing, check out the _Advanced: +Multiple guests_ section. The same principles can be applied to other routing +methods with a bit more effort. + +For the choice of firewall, `nft` is recommended for use on production Linux +systems, but, for the sake of compatibility, this guide provides a choice +between either `nft` or the `iptables-nft` translation layer. The latter is +[no longer recommended](https://access.redhat.com/solutions/6739041) but may be +more familiar to readers. + +## On the Host + +The first step on the host for any microVM is to create a Linux `tap` device, +which Firecracker will use for networking. + +For this setup, only two IP addresses will be necessary - one for the `tap` +device and one for the guest itself, through which you will, for example, `ssh` +into the guest. So, we'll choose the smallest IPv4 subnet needed for 2 +addresses: `/30`. For this VM, let's use the `172.16.0.1` `tap` IP and the +`172.16.0.2` guest IP. -## On The Host +```bash +# Create the tap device. +sudo ip tuntap add tap0 mode tap +# Assign it the tap IP and start up the device. +sudo ip addr add 172.16.0.1/30 dev tap0 +sudo ip link set tap0 up +``` -The first step on the host is to create a `tap` device: +**Note:** The IP of the TAP device should be chosen such that it's not in the +same subnet as the IP address of the host. + +We'll need to enable IPv4 forwarding on the system. ```bash -sudo ip tuntap add tap0 mode tap +echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward ``` -Then you have a few options for routing traffic out of the tap device, through -your host's network interface. One option is NAT, set up like this: +### Configuration via `nft` + +We'll need an nftables table for our routing needs, and 2 chains inside that +table: one for NAT on `postrouting` stage, and another one for filtering on +`forward` stage: ```bash -sudo ip addr add 172.16.0.1/24 dev tap0 -sudo ip link set tap0 up -sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" -sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT +sudo nft add table firecracker +sudo nft 'add chain firecracker postrouting { type nat hook postrouting priority srcnat; policy accept; }' +sudo nft 'add chain firecracker filter { type filter hook forward priority filter; policy accept; }' ``` -*Note:* The IP of the TAP device should be chosen such that it's not in the same -subnet as the IP address of the host. +The first rule we'll need will masquerade packets from the guest IP as if they +came from the host's IP, by changing the source IP address of these packets: -*Advanced:* If you are running multiple Firecracker MicroVMs in parallel, or -have something else on your system using `tap0` then you need to create a `tap` -for each one, with a unique name. +```bash +sudo nft add rule firecracker postrouting ip saddr 172.16.0.2 oifname eth0 counter masquerade +``` -*Advanced:* You also need to do the `iptables` set up for each new `tap`. If you -have `iptables` rules you care about on your host, you may want to save those -rules before starting. +The second rule we'll need will accept packets from the tap IP (the guest will +use the tap IP as its gateway and will therefore route its own packets through +the tap IP) and direct them to the host network interface: ```bash -sudo iptables-save > iptables.rules.old +sudo nft add rule firecracker filter iifname tap0 oifname eth0 accept +``` + +### Configuration via `iptables-nft` + +Tables and chains are managed by `iptables-nft` automatically, but we'll need +three rules to perform the NAT steps: + +```bash +sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE +sudo iptables-nft -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +sudo iptables-nft -A FORWARD -i tap0 -o eth0 -j ACCEPT ``` ## Setting Up Firecracker @@ -85,14 +144,20 @@ configuration file like this: ``` Alternatively, if you are using firectl, add ---tap-device=tap0/06:00:AC:10:00:02\` to your command line. +`--tap-device=tap0/06:00:AC:10:00:02\` to your command line. ## In The Guest -Once you have booted the guest, bring up networking within the guest: +Once you have booted the guest, it will have its networking interface with the +name specified by `iface_id` in the Firecracker configuration. + +You'll now need to assign the guest its IP, activate the guest's networking +interface and set up the `tap` IP as the guest's gateway address, so that +packets are routed through the `tap` device, where they are then picked up by +the setup on the host prepared before: ```bash -ip addr add 172.16.0.2/24 dev eth0 +ip addr add 172.16.0.2/30 dev eth0 ip link set eth0 up ip route add default via 172.16.0.1 dev eth0 ``` @@ -107,23 +172,183 @@ your environment. For testing, you can add a public DNS server to nameserver 8.8.8.8 ``` -## \[Advanced\] Setting Up a Bridge Interface +**Note:** Sometimes, it's undesirable to have `iproute2` (providing the `ip` +command) installed on your guest OS, or you simply want to have these steps be +performed automatically. To do this, check out the _Advanced: Guest network +configuration using kernel command line_ section. + +## Cleaning up + +The first step to cleaning up is to delete the tap device on the host: + +```bash +sudo ip link del tap0 +``` + +### Cleanup using `nft` + +You'll want to delete the two nftables rules for NAT routing from the +`postrouting` and `filter` chains. To do this with nftables, you'll need to look +up the _handles_ (identifiers) of these rules by running: + +```bash +sudo nft -a list ruleset +``` + +Now, find the `# handle` comments relating to the two rules and delete them. For +example, if the handle to the masquerade rule is 1 and the one to the forwarding +rule is 2: + +```bash +sudo nft delete rule firecracker postrouting handle 1 +sudo nft delete rule firecracker filter handle 2 +``` + +Run the following steps only **if you have no more guests** running on the host: + +Set IPv4 forwarding back to disabled: + +```bash +echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward +``` + +If you're using `nft`, delete the `firecracker` table to revert your nftables +configuration fully back to its initial state: + +```bash +sudo nft delete table firecracker +``` + +### Cleanup using `iptables-nft` + +Of the configured `iptables-nft` rules, two should be deleted if you have guests +remaining in your configuration: + +```bash +sudo iptables-nft -t nat -D POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE +sudo iptables-nft -D FORWARD -i tap0 -o eth0 -j ACCEPT +``` + +**If you have no more guests** running on the host, then similarly set IPv4 +forwarding back to disabled: + +```bash +echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward +``` + +And delete the remaining `conntrack` rule that applies to all guests: + +```bash +sudo iptables-nft -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +``` + +If nothing else is using `iptables-nft` on the system, you may even want to +delete the entire system ruleset like so: + +```bash +sudo iptables-nft -F +sudo iptables-nft -t nat -F +``` + +## Advanced: Multiple guests + +To configure multiple guests, we will only need to repeat some of the steps in +this setup for each of the microVMs: + +1. Each microVM has its own subnet and the two IP addresses inside of it: the + `tap` IP and the guest IP. +1. Each microVM has its own two nftables rules for masquerading and forwarding, + while the same table and two chains can be shared between the microVMs. +1. Each microVM has its own routing configuration inside the guest itself + (achieved through `iproute2` or the method described in the _Advanced: Guest + network configuration at kernel level_ section). + +To give a more concrete example, **let's add a second microVM** to the one +you've already configured: + +Let's assume we allocate /30 subnets in the 172.16.0.0/16 range sequentially to +give out as few addresses as needed. + +The next /30 subnet in the 172.16.0.0/16 range will give us these two IPs: +172.16.0.5 as the `tap` IP and 172.16.0.6 as the guest IP. + +Our new `tap` device will, sequentially, have the name `tap1`: + +```bash +sudo ip tuntap add tap1 mode tap +sudo ip addr add 172.16.0.5/30 dev tap1 +sudo ip link set tap1 up +``` + +Now, let's add the new two `nft` rules, also with the new values: + +```bash +sudo nft add rule firecracker postrouting ip saddr 172.16.0.6 oifname eth0 counter masquerade +sudo nft add rule firecracker filter iifname tap1 oifname eth0 accept +``` + +If using `iptables-nft`, add the rules like so: + +```bash +sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.6 -j MASQUERADE +sudo iptables-nft -A FORWARD -i tap1 -o eth0 -j ACCEPT +``` + +Modify your Firecracker configuration with the `host_dev_name` now being `tap1` +instead of `tap0`, boot up the guest and perform the routing inside of it like +so, changing the guest IP and `tap` IP: + +```bash +ip addr add 172.16.0.6/30 dev eth0 +ip link set eth0 up +ip route add default via 172.16.0.5 dev eth0 +``` + +Or, you can use the setup from _Advanced: Guest network configuration at kernel +level_ by simply changing the G and T variables, i.e. the guest IP and `tap` IP. + +**Note:** if you'd like to calculate the guest and `tap` IPs using the +sequential subnet allocation method that has been used here, you can use the +following formulas specific to IPv4 addresses: + +`tap` IP = `172.16.[(A*O+1)/256].[(A*O+1)%256]`. + +Guest IP = `172.16.[(A*O+2)/256].[(A*O+2)%256]`. + +Round down the division and replace `A` with the amount of IP addresses inside +your subnet (for a /30 subnet, that will be 4 addresses, for example) and +replace `O` with the sequential number of your microVM, starting at 0. You can +replace `172.16` with any other values that fit between between 1 and 255 as +usual with an IPv4 address. + +For example, let's calculate the addresses of the 1000-th microVM with a /30 +subnet in the `172.16.0.0/16` range: + +`tap` IP = `172.16.[(4*999+1)/256].[(4*999+1)%256]` = `172.16.15.157`. + +Guest IP = `172.16.[(4*999+2)/256].[(4*999+2)%256]` = `172.16.15.158`. + +This allocation setup has been used successfully in the `firecracker-demo` +project for launching several thousand microVMs on the same host: +[relevant lines](https://github.com/firecracker-microvm/firecracker-demo/blob/63717c6e7fbd277bdec8e26a5533d53544a760bb/start-firecracker.sh#L45). + +## Advanced: Bridge-based routing ### On The Host -1. Create a bridge interface +1. Create a bridge interface: ```bash sudo ip link add name br0 type bridge ``` -1. Add tap interface [created above](#on-the-host) to the bridge +1. Add the `tap` device [created above](#on-the-host) to the bridge: ```bash sudo ip link set dev tap0 master br0 ``` -1. Define an IP address in your network for the bridge. +1. Define an IP address in your network for the bridge: For example, if your gateway were on `192.168.1.1` and you wanted to use this for getting dynamic IPs, you would want to give the bridge an unused IP @@ -133,24 +358,30 @@ nameserver 8.8.8.8 sudo ip address add 192.168.1.7/24 dev br0 ``` -1. Add firewall rules to allow traffic to be routed to the guest +1. Add a firewall rule to allow traffic to be routed to the guest: ```bash sudo iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE ``` +1. Once you're cleaning up the configuration, make sure to delete the bridge: + + ```bash + sudo ip link del br0 + ``` + ### On The Guest 1. Define an unused IP address in the bridge's subnet e.g., `192.168.1.169/24`. - _Note: Alternatively, you could rely on DHCP for getting a dynamic IP address - from your gateway._ + **Note**: Alternatively, you could rely on DHCP for getting a dynamic IP + address from your gateway. ```bash ip addr add 192.168.1.169/24 dev eth0 ``` -1. Set the interface up. +1. Enable the network interface: ```bash ip link set eth0 up @@ -177,43 +408,38 @@ nameserver 8.8.8.8 192.168.1.1 via 192.168.1.7 dev eth0 ``` -1. Add your nameserver to `resolve.conf` +1. Add your nameserver to `/etc/resolve.conf` ```bash # cat /etc/resolv.conf nameserver 192.168.1.1 ``` -## Cleaning up +## Advanced: Guest network configuration using kernel command line -The first step to cleaning up is deleting the tap device: +The Linux kernel supports an `ip` CLI arguments that can be passed to it when +booting. Boot arguments in Firecracker are configured in the `boot_args` +property of the boot source (`boot-source` object in the JSON configuration or +the equivalent endpoint in the API server). -```bash -sudo ip link del tap0 -``` +The value of the `ip` CLI argument for our setup will be the of this format: +`G::T:GM::GI:off`. G is the guest IP (without the subnet), T is the `tap` IP +(without the subnet), GM is the "long" mask IP of the guest CIDR and GI is the +name of the guest network interface. -If you don't have anything else using `iptables` on your machine, clean up those -rules: - -```bash -sudo iptables -F -sudo sh -c "echo 0 > /proc/sys/net/ipv4/ip_forward" # usually the default -``` +Substituting our values, we get: +`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off`. Insert this at the end of +your boot arguments for your microVM, and the guest Linux kernel will +automatically perform the routing configuration done in the _In the Guest_ +section without needing `iproute2` installed in the guest. -If you have an existing iptables setup, you'll want to be more careful about -cleaning up. +As soon as you boot the guest, it will already be connected to the network +(assuming you correctly performing the other steps). -*Advanced:* If you saved your iptables rules in the first step, then you can -restore them like this: +**Note**: you can also use the `ip` argument to configure a primary DNS server +and, optionally, a second DNS server without needing to touch +`/etc/resolv.conf`. As an example: -```bash -if [ -f iptables.rules.old ]; then - sudo iptables-restore < iptables.rules.old -fi -``` - -*Advanced:* If you created a bridge interface, delete it using the following: - -```bash -sudo ip link del br0 -``` +`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off:8.8.8.8:1.1.1.1` configures +`8.8.8.8` as the primary DNS server and `1.1.1.1` as the secondary DNS server, +as well as the rest of the guest-side routing. From 8f48d3d54a001840d342e0f3e86ebf9f52724c37 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 20 Nov 2024 12:00:41 +0000 Subject: [PATCH 043/464] fix: add vcpu_features and kvm_capabilites to swagger These fields were added in #3967 but the Swagger API definition was not updated. This patch fixes the API definition. Also, the field type is changed from "string" to "object", as it has properties and thus can't be a string. Signed-off-by: Riccardo Mancini --- src/firecracker/swagger/firecracker.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index 06f449db431..20bad48bf64 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -840,7 +840,7 @@ definitions: default: "None" CpuConfig: - type: string + type: object description: The CPU configuration template defines a set of bit maps as modifiers of flags accessed by register to be disabled/enabled for the microvm. @@ -854,6 +854,12 @@ definitions: reg_modifiers: type: object description: A collection of registers to be modified. (aarch64) + vcpu_features: + type: object + description: A collection of vcpu features to be modified. (aarch64) + kvm_capabilities: + type: object + description: A collection of kvm capabilities to be modified. (aarch64) Drive: type: object From 4352366ba8f5bb09b5226710c29c1575e59ce0ec Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 20 Nov 2024 16:16:17 +0000 Subject: [PATCH 044/464] chore: add changelog entry for swagger CpuConfig fix Add an entry to mention that we fixed the Swagger API definition. Signed-off-by: Riccardo Mancini --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7da89123eab..6e7be8f518f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ and this project adheres to ### Fixed +- [#4921](https://github.com/firecracker-microvm/firecracker/pull/4921): Fixed + swagger `CpuConfig` definition to include missing aarch64-specific fields. + ## \[1.10.1\] ### Changed From cabeb7eece9ff02869392380c949f27b80d99478 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 25 Nov 2024 10:26:13 +0000 Subject: [PATCH 045/464] replace `set([...])` with set literal My IDE was complaining about this Signed-off-by: Patrick Roy --- tests/framework/utils_cpu_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 96bf197efda..e57ecfe72c7 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -29,7 +29,7 @@ def get_supported_cpu_templates(): match get_cpu_vendor(), global_props.cpu_codename: # T2CL template is only supported on Cascade Lake and newer CPUs. case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: - return sorted(set(INTEL_TEMPLATES) - set(["T2CL"])) + return sorted(set(INTEL_TEMPLATES) - {"T2CL"}) case CpuVendor.INTEL, _: return INTEL_TEMPLATES case CpuVendor.AMD, _: From 350bfb37c6fb7852c5426f4bc108ac3f9efceb90 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 25 Nov 2024 10:51:36 +0000 Subject: [PATCH 046/464] chore: make sure hexadecimal numbers are prefixed by '0x' I got an error message saying 'Start microvm error: Internal error while starting microVM: Vm error: Missing KVM capabilities: aa', which just looked like KVM was screaming. Thus, look through where we print hex numbers, and make sure they are prefixed using '0x', and do so uniformly by using Rust's `:#x` format modifier [1] [1]: https://doc.rust-lang.org/std/fmt/#sign0 Signed-off-by: Patrick Roy --- src/vmm/src/devices/virtio/device.rs | 2 +- src/vmm/src/devices/virtio/mmio.rs | 22 +++++++--------------- src/vmm/src/devices/virtio/vsock/device.rs | 2 +- src/vmm/src/gdb/target.rs | 6 +++--- src/vmm/src/vstate/vcpu/x86_64.rs | 4 ++-- src/vmm/src/vstate/vm.rs | 2 +- 6 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs index b5af6862af9..5adf4873dc6 100644 --- a/src/vmm/src/devices/virtio/device.rs +++ b/src/vmm/src/devices/virtio/device.rs @@ -156,7 +156,7 @@ pub trait VirtioDevice: AsAny + Send { let avail_features = self.avail_features(); let unrequested_features = v & !avail_features; if unrequested_features != 0 { - warn!("Received acknowledge request for unknown feature: {:x}", v); + warn!("Received acknowledge request for unknown feature: {:#x}", v); // Don't count these features as acked. v &= !unrequested_features; } diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs index 463d11ca2e2..f734058c5b1 100644 --- a/src/vmm/src/devices/virtio/mmio.rs +++ b/src/vmm/src/devices/virtio/mmio.rs @@ -138,7 +138,7 @@ impl MmioTransport { self.with_queue_mut(f); } else { warn!( - "update virtio queue in invalid state 0x{:x}", + "update virtio queue in invalid state {:#x}", self.device_status ); } @@ -227,7 +227,7 @@ impl MmioTransport { } _ => { warn!( - "invalid virtio driver status transition: 0x{:x} -> 0x{:x}", + "invalid virtio driver status transition: {:#x} -> {:#x}", self.device_status, status ); } @@ -282,7 +282,7 @@ impl MmioTransport { 0x70 => self.device_status, 0xfc => self.config_generation, _ => { - warn!("unknown virtio mmio register read: 0x{:x}", offset); + warn!("unknown virtio mmio register read: {:#x}", offset); return; } }; @@ -290,11 +290,7 @@ impl MmioTransport { } 0x100..=0xfff => self.locked_device().read_config(offset - 0x100, data), _ => { - warn!( - "invalid virtio mmio read: 0x{:x}:0x{:x}", - offset, - data.len() - ); + warn!("invalid virtio mmio read: {:#x}:{:#x}", offset, data.len()); } }; } @@ -324,7 +320,7 @@ impl MmioTransport { .ack_features_by_page(self.acked_features_select, v); } else { warn!( - "ack virtio features in invalid state 0x{:x}", + "ack virtio features in invalid state {:#x}", self.device_status ); } @@ -346,7 +342,7 @@ impl MmioTransport { 0xa0 => self.update_queue_field(|q| lo(&mut q.used_ring_address, v)), 0xa4 => self.update_queue_field(|q| hi(&mut q.used_ring_address, v)), _ => { - warn!("unknown virtio mmio register write: 0x{:x}", offset); + warn!("unknown virtio mmio register write: {:#x}", offset); } } } @@ -361,11 +357,7 @@ impl MmioTransport { } } _ => { - warn!( - "invalid virtio mmio write: 0x{:x}:0x{:x}", - offset, - data.len() - ); + warn!("invalid virtio mmio write: {:#x}:{:#x}", offset, data.len()); } } } diff --git a/src/vmm/src/devices/virtio/vsock/device.rs b/src/vmm/src/devices/virtio/vsock/device.rs index bf438aca99f..eb7c144c4be 100644 --- a/src/vmm/src/devices/virtio/vsock/device.rs +++ b/src/vmm/src/devices/virtio/vsock/device.rs @@ -322,7 +322,7 @@ where fn write_config(&mut self, offset: u64, data: &[u8]) { METRICS.cfg_fails.inc(); warn!( - "vsock: guest driver attempted to write device config (offset={:x}, len={:x})", + "vsock: guest driver attempted to write device config (offset={:#x}, len={:#x})", offset, data.len() ); diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index fc2da289e8a..b8230342b27 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -390,7 +390,7 @@ impl MultiThreadBase for FirecrackerTarget { while !data.is_empty() { let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| { - error!("Error {e:?} translating gva on read address: {gva:X}"); + error!("Error {e:?} translating gva on read address: {gva:#X}"); })?; // Compute the amount space left in the page after the gpa @@ -424,7 +424,7 @@ impl MultiThreadBase for FirecrackerTarget { while !data.is_empty() { let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| { - error!("Error {e:?} translating gva on read address: {gva:X}"); + error!("Error {e:?} translating gva on read address: {gva:#X}"); })?; // Compute the amount space left in the page after the gpa @@ -436,7 +436,7 @@ impl MultiThreadBase for FirecrackerTarget { vmm.guest_memory() .write(&data[..write_len], GuestAddress(gpa)) .map_err(|e| { - error!("Error {e:?} writing memory at {gpa:X}"); + error!("Error {e:?} writing memory at {gpa:#X}"); })?; data = &data[write_len..]; diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 6fee3933435..a1bb22d1bb7 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -61,7 +61,7 @@ pub enum KvmVcpuError { VcpuGetLapic(kvm_ioctls::Error), /// Failed to get KVM vcpu mp state: {0} VcpuGetMpState(kvm_ioctls::Error), - /// Failed to get KVM vcpu msr: 0x{0:x} + /// Failed to get KVM vcpu msr: {0:#x} VcpuGetMsr(u32), /// Failed to get KVM vcpu msrs: {0} VcpuGetMsrs(kvm_ioctls::Error), @@ -321,7 +321,7 @@ impl KvmVcpu { .filter(|msr| msr.index == MSR_IA32_TSC_DEADLINE && msr.data == 0) .for_each(|msr| { warn!( - "MSR_IA32_TSC_DEADLINE is 0, replacing with {:x}.", + "MSR_IA32_TSC_DEADLINE is 0, replacing with {:#x}.", tsc_value ); msr.data = tsc_value; diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 0f72abcf68f..3d24dc6f9ac 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -34,7 +34,7 @@ use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRe pub enum VmError { /// The host kernel reports an invalid KVM API version: {0} ApiVersion(i32), - /// Missing KVM capabilities: {0:x?} + /// Missing KVM capabilities: {0:#x?} Capabilities(u32), /** Error creating KVM object: {0} Make sure the user launching the firecracker process is \ configured on the /dev/kvm file's ACL. */ From 1320786a7aad600769815cf0450db35508da340c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 25 Nov 2024 10:12:59 +0000 Subject: [PATCH 047/464] fix: make aarch64_with_sve_and_pac template work with >=2 vcpus Setting the least significant 4 bits to zero overwrites some configuration that Firecracker sets on secondary CPUs that is needed for them to be able to be booted. With these 4 bits set to 0, the CPUs will never show up as online inside the guest, and KVM will just infinitely spin inside KVM_RUN for them. Fix by using 'x' in the template, which preserves the defaults set by Firecracker. Signed-off-by: Patrick Roy --- tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json b/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json index b155d81dc34..29e47be4a92 100644 --- a/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json +++ b/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json @@ -1,4 +1,4 @@ { "kvm_capabilities": ["170", "171", "172"], - "vcpu_features": [{ "index": 0, "bitmap": "0b1110000" }] + "vcpu_features": [{ "index": 0, "bitmap": "0b111xxxx" }] } From 46ba7487ec8808e771fd4f0947f398fe4fc2c79c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 15 Nov 2024 10:33:18 +0000 Subject: [PATCH 048/464] refactor: Remove some getters and setters for boot_source The initialization code for the `boot_source` field in `build_boot_source` had me do a double take when I first saw, with all the setters and getters obscuring what is really happening. Clean this up by simply using a struct initializer, and also remove the getters and setters altogether, since all the fields are pub anyway. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 6 ++++-- src/vmm/src/persist.rs | 2 +- src/vmm/src/resources.rs | 37 ++++++++----------------------------- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 1f52fdad063..3355633e3c8 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -259,7 +259,9 @@ pub fn build_microvm_for_boot( let request_ts = TimestampUs::default(); let boot_config = vm_resources - .boot_source_builder() + .boot_source + .builder + .as_ref() .ok_or(MissingKernelConfig)?; let guest_memory = vm_resources @@ -508,7 +510,7 @@ pub fn build_microvm_from_snapshot( vmm.vm.restore_state(µvm_state.vm_state)?; // Restore the boot source config paths. - vm_resources.set_boot_source_config(microvm_state.vm_info.boot_source); + vm_resources.boot_source.config = microvm_state.vm_info.boot_source; // Restore devices states. let mmio_ctor_args = MMIODevManagerConstructorArgs { diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 5b01ed49c75..3479e0b6309 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -64,7 +64,7 @@ impl From<&VmResources> for VmInfo { mem_size_mib: value.vm_config.mem_size_mib as u64, smt: value.vm_config.smt, cpu_template: StaticCpuTemplate::from(&value.vm_config.cpu_template), - boot_source: value.boot_source_config().clone(), + boot_source: value.boot_source.config.clone(), huge_pages: value.vm_config.huge_pages, } } diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index a4d15641975..0ad4df8aa19 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -315,16 +315,6 @@ impl VmResources { mmds_config } - /// Gets a reference to the boot source configuration. - pub fn boot_source_config(&self) -> &BootSourceConfig { - &self.boot_source.config - } - - /// Gets a reference to the boot source builder. - pub fn boot_source_builder(&self) -> Option<&BootConfig> { - self.boot_source.builder.as_ref() - } - /// Sets a balloon device to be attached when the VM starts. pub fn set_balloon_device( &mut self, @@ -354,14 +344,12 @@ impl VmResources { return Err(BootSourceConfigError::HugePagesAndInitRd); } - self.set_boot_source_config(boot_source_cfg); - self.boot_source.builder = Some(BootConfig::new(self.boot_source_config())?); - Ok(()) - } + self.boot_source = BootSource { + builder: Some(BootConfig::new(&boot_source_cfg)?), + config: boot_source_cfg, + }; - /// Set the boot source configuration (contains raw kernel config details). - pub fn set_boot_source_config(&mut self, boot_source_cfg: BootSourceConfig) { - self.boot_source.config = boot_source_cfg; + Ok(()) } /// Inserts a block to be attached when the VM starts. @@ -512,7 +500,7 @@ impl From<&VmResources> for VmmConfig { VmmConfig { balloon_device: resources.balloon.get_config().ok(), block_devices: resources.block.configs(), - boot_source: resources.boot_source_config().clone(), + boot_source: resources.boot_source.config.clone(), cpu_config: None, logger: None, machine_config: Some(MachineConfig::from(&resources.vm_config)), @@ -1521,15 +1509,6 @@ mod tests { assert_eq!(actual_entropy_cfg, entropy_device_cfg); } - #[test] - fn test_boot_config() { - let vm_resources = default_vm_resources(); - let expected_boot_cfg = vm_resources.boot_source.builder.as_ref().unwrap(); - let actual_boot_cfg = vm_resources.boot_source_builder().unwrap(); - - assert!(actual_boot_cfg == expected_boot_cfg); - } - #[test] fn test_set_boot_source() { let tmp_file = TempFile::new().unwrap(); @@ -1541,7 +1520,7 @@ mod tests { }; let mut vm_resources = default_vm_resources(); - let boot_builder = vm_resources.boot_source_builder().unwrap(); + let boot_builder = vm_resources.boot_source.builder.as_ref().unwrap(); let tmp_ino = tmp_file.as_file().metadata().unwrap().st_ino(); assert_ne!( @@ -1568,7 +1547,7 @@ mod tests { ); vm_resources.build_boot_source(expected_boot_cfg).unwrap(); - let boot_source_builder = vm_resources.boot_source_builder().unwrap(); + let boot_source_builder = vm_resources.boot_source.builder.unwrap(); assert_eq!( boot_source_builder .cmdline From 63ea863e6ca0ca37c52f95083c199f82eb157d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 26 Nov 2024 17:34:31 +0100 Subject: [PATCH 049/464] docs: fix Firecracker version and rootfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the last change we missed updating the Firecracker CI version. Also keep the rootfs as ext4 for the rest of the guide. Fixes: a69595f5f03757bd990318e7aa4f23409355ae13 Signed-off-by: Pablo Barbáchano --- docs/getting-started.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 644d31e78a8..1b55fbf3230 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -100,21 +100,23 @@ kernel image with a Ubuntu 24.04 rootfs from our CI: ```bash ARCH="$(uname -m)" -latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.10/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)") +latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.11/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.11/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)") # Download a linux kernel binary wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" # Download a rootfs -wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.squashfs" +wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.11/${ARCH}/ubuntu-24.04.squashfs" # Create an ssh key for the rootfs unsquashfs ubuntu-24.04.squashfs.upstream ssh-keygen -f id_rsa -N "" cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys mv -v id_rsa ./ubuntu-24.04.id_rsa -# re-squash -mksquashfs squashfs-root ubuntu-24.04.squashfs -all-root -noappend -comp zstd +# create ext4 filesystem image +sudo chown -R root:root squashfs-root +truncate -s 400M ubuntu-24.04.ext4 +sudo mkfs.ext4 -d squashfs-root -F ubuntu-24.04.ext4 ``` ### Getting a Firecracker Binary From 4c338535750e88172c5c14a4f5667e253a6e84d7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 27 Nov 2024 10:24:35 +0000 Subject: [PATCH 050/464] fix: ensure ci artifacts are present when using devtool sandbox Without ensure_ci_artifacts called inside cmd_sandbox, you will see an index out of bounds errors during set up of the argument parser, since build/img will be an empty directory (e.g. there are no kernels to select, and the -1 index will be out of bounds). Reported-by: Jack Thomson Signed-off-by: Patrick Roy --- tools/devtool | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/devtool b/tools/devtool index c3b7b27ed98..3e0bc857ed5 100755 --- a/tools/devtool +++ b/tools/devtool @@ -890,6 +890,7 @@ cmd_sh() { cmd_sandbox() { cmd_build --release + ensure_ci_artifacts cmd_sh "tmux new env PYTEST_ADDOPTS=--pdbcls=IPython.terminal.debugger:TerminalPdb PYTHONPATH=tests IPYTHONDIR=\$PWD/.ipython ipython -i ./tools/sandbox.py $@" } From 555563b1b463bc1755f5573e2970b3a08ae7f84a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 28 Nov 2024 13:37:28 +0000 Subject: [PATCH 051/464] fix: properly setup outbound network connectivity in getting started MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the getting started guide was hardcoding eth0 as the network interface on the host to route outbound microvm network traffic to. However, on EC2 instances (and my laptop), that's wrong, because its not called eth0. So instead dynamically determine the hopefully correct network interface on the host. Fixes: #4930 Suggested-by: Pablo Barbáchano Signed-off-by: Patrick Roy --- docs/getting-started.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 1b55fbf3230..02a2077207b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -197,17 +197,16 @@ sudo ip link set dev "$TAP_DEV" up # Enable ip forwarding sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" +sudo iptables -P FORWARD ACCEPT -HOST_IFACE="eth0" +# This tries to determine the name of the host network interface to forward +# VM's outbound network traffic through. If outbound traffic doesn't work, +# double check this returns the correct interface! +HOST_IFACE=$(ip -j route list default |jq -r '.[0].dev') # Set up microVM internet access sudo iptables -t nat -D POSTROUTING -o "$HOST_IFACE" -j MASQUERADE || true -sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT \ - || true -sudo iptables -D FORWARD -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT || true sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE -sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -sudo iptables -I FORWARD 1 -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT API_SOCKET="/tmp/firecracker.socket" LOGFILE="./firecracker.log" From 1e3d4e9a08318134f072ccca91006181dd684091 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:49:41 +0000 Subject: [PATCH 052/464] build(deps): Bump the firecracker group across 1 directory with 14 updates Bumps the firecracker group with 14 updates in the / directory: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.10` | `0.8.11` | | [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.89` | `1.0.92` | | [syn](https://github.com/dtolnay/syn) | `2.0.87` | `2.0.89` | | [libc](https://github.com/rust-lang/libc) | `0.2.164` | `0.2.167` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.11.0` | `1.11.1` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.12.14` | `0.12.15` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.23.0` | `0.23.1` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.1` | `1.2.2` | | [cmake](https://github.com/rust-lang/cmake-rs) | `0.1.51` | `0.1.52` | | [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.15` | `0.2.16` | | [errno](https://github.com/lambda-fairy/rust-errno) | `0.3.9` | `0.3.10` | | [hashbrown](https://github.com/rust-lang/hashbrown) | `0.15.1` | `0.15.2` | | [itoa](https://github.com/dtolnay/itoa) | `1.0.11` | `1.0.14` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.40` | `0.38.41` | Updates `zerocopy` from 0.8.10 to 0.8.11 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.10...v0.8.11) Updates `proc-macro2` from 1.0.89 to 1.0.92 - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.89...1.0.92) Updates `syn` from 2.0.87 to 2.0.89 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.87...2.0.89) Updates `libc` from 0.2.164 to 0.2.167 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.167/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.164...0.2.167) Updates `aws-lc-rs` from 1.11.0 to 1.11.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.11.0...v1.11.1) Updates `aws-lc-fips-sys` from 0.12.14 to 0.12.15 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.12.14...aws-lc-fips-sys/v0.12.15) Updates `aws-lc-sys` from 0.23.0 to 0.23.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.23.0...aws-lc-sys/v0.23.1) Updates `cc` from 1.2.1 to 1.2.2 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.1...cc-v1.2.2) Updates `cmake` from 0.1.51 to 0.1.52 - [Release notes](https://github.com/rust-lang/cmake-rs/releases) - [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.51...v0.1.52) Updates `cpufeatures` from 0.2.15 to 0.2.16 - [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.15...cpufeatures-v0.2.16) Updates `errno` from 0.3.9 to 0.3.10 - [Release notes](https://github.com/lambda-fairy/rust-errno/releases) - [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md) - [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.9...v0.3.10) Updates `hashbrown` from 0.15.1 to 0.15.2 - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/commits) Updates `itoa` from 1.0.11 to 1.0.14 - [Release notes](https://github.com/dtolnay/itoa/releases) - [Commits](https://github.com/dtolnay/itoa/compare/1.0.11...1.0.14) Updates `rustix` from 0.38.40 to 0.38.41 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.40...v0.38.41) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cmake dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cpufeatures dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: errno dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: hashbrown dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: itoa dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 75 +++++++++++++--------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 4 +- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 4 +- src/jailer/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 6 +-- 12 files changed, 50 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3ad7e16b54..c3fed9c404a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.3", "vm-memory", - "zerocopy 0.8.10", + "zerocopy 0.8.11", ] [[package]] @@ -125,9 +125,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8671005a9c1e80bd3dc9aee84c5bfd594d32a3d645fdb56d5d9d5e26daa4c315" +checksum = "df1e8a8e212a7851ef3d4c28cdfc017072bc684f0e0f57c7943ab60f695c3bfb" dependencies = [ "bindgen 0.69.5", "cc", @@ -140,13 +140,12 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", - "mirai-annotations", "paste", "untrusted", "zeroize", @@ -154,9 +153,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" dependencies = [ "bindgen 0.69.5", "cc", @@ -261,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -403,9 +402,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -433,9 +432,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -586,12 +585,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -707,9 +706,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -794,9 +793,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jailer" @@ -857,9 +856,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" @@ -955,12 +954,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "nix" version = "0.27.1" @@ -1067,9 +1060,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1187,9 +1180,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -1323,9 +1316,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -1630,7 +1623,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.10", + "zerocopy 0.8.11", ] [[package]] @@ -1807,11 +1800,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13a42ed30c63171d820889b2981318736915150575b8d2d6dbee7edd68336ca" +checksum = "cce3b5629d87654b53a49002acc2ce64aa5aa7255f5c718374a37ac7fd98c218" dependencies = [ - "zerocopy-derive 0.8.10", + "zerocopy-derive 0.8.11", ] [[package]] @@ -1827,9 +1820,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "593e7c96176495043fcb9e87cf7659f4d18679b5bab6b92bdef359c76a7795dd" +checksum = "74a82c26c3986af2623ec9eb890ff4aa19c006e30a1133dc9bd1830ec1612e20" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 15137400180..39b8f1574c9 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.3" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.10", features = ["derive"] } +zerocopy = { version = "0.8.11", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 91e03a2afb8..f316fa884dc 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -12,9 +12,9 @@ bench = false [dependencies] clap = { version = "4.5.21", features = ["derive"] } itertools = "0.13.0" -proc-macro2 = { version = "1.0.89", features = ["span-locations"] } +proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" -syn = { version = "2.0.85", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.89", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 6654bb090c4..eb7c16472e0 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -12,7 +12,7 @@ bench = false [dependencies] clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 8d0889c23dd..6cd237aaabe 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -34,7 +34,7 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.20.5" -libc = "0.2.164" +libc = "0.2.167" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 55b50efb785..ef9162027be 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,7 +12,7 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index fd25f4ffe08..660a7cbb7cd 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -11,9 +11,9 @@ proc-macro = true bench = false [dependencies] -proc-macro2 = "1.0.89" +proc-macro2 = "1.0.92" quote = "1.0.37" -syn = { version = "2.0.85", features = ["full", "extra-traits"] } +syn = { version = "2.0.89", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index c944f5f346d..1615260b03b 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } thiserror = "2.0.3" vmm-sys-util = "0.12.1" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 1916a085b51..90477e3e025 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 022342d896f..91bbebf7f27 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.21", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" thiserror = "2.0.3" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 2514ee05b0b..7f57e5081a0 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.164" +libc = "0.2.167" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.3" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 070cae5088f..283a47a5982 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.11.0", features = ["bindgen"] } +aws-lc-rs = { version = "1.11.1", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.6.0" @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.164" +libc = "0.2.167" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -46,7 +46,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.10" } +zerocopy = { version = "0.8.11" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 7f3715f4310f18507c78381a3636d8260a017db1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 09:34:33 +0000 Subject: [PATCH 053/464] devtool: do not call ensure_ci_artifacts in cmd_sh This already caused a recursive call between ensure_ci_artifacts and cmd_sh (since the former calls the later), which was only benign because ensure_ci_artifacts exits early if the directory exists. With the next patch, it will use cmd_sh before creating the directory, so break this recursion once and for all by instead making the call-sites of cmd_sh that require artifacts to just ensure them themselves. Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 3e0bc857ed5..200dcc43b10 100755 --- a/tools/devtool +++ b/tools/devtool @@ -878,7 +878,6 @@ cmd_shell() { cmd_sh() { ensure_build_dir - ensure_ci_artifacts run_devctr \ --privileged \ --ulimit nofile=4096:4096 \ @@ -916,6 +915,7 @@ cmd_sandbox_native() { } cmd_test_debug() { + ensure_ci_artifacts cmd_sh "tmux new ./tools/test.sh --pdb $@" } From aed4abec4a28128fe7177480b81aebb407d855f1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 07:50:06 +0000 Subject: [PATCH 054/464] devtool: resolve artifact version from Cargo.toml automatically determine the version of the artifacts folder from the Firecracker version in Cargo.toml. Eliminates one of the things we have to manually update during the release. Signed-off-by: Patrick Roy --- tools/devtool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 200dcc43b10..d3a59f7c5b2 100755 --- a/tools/devtool +++ b/tools/devtool @@ -562,7 +562,8 @@ ensure_ci_artifacts() { # Fetch all the artifacts so they are local say "Fetching CI artifacts from S3" - S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(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) ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m) if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS From 4b9df906d2da5396eb1244576c5f21b983441e53 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 07:57:49 +0000 Subject: [PATCH 055/464] devtool: add `download_ci_artifacts` command Every now and then, I managed to end up with an empty CI artifacts folder, for whatever reason (mostly me being silly). The solution is generally to remove whatever messed up stuff I ended up with in build/img, and run some arbitrary devtool command that I know will redownload everything. Similar workflows must happen whenever we do an in-place update of our CI artifacts. Abstract this away into a command that deletes the build/img folder, and then redownloads it. Signed-off-by: Patrick Roy --- tools/devtool | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/devtool b/tools/devtool index d3a59f7c5b2..4019a7f4b1e 100755 --- a/tools/devtool +++ b/tools/devtool @@ -418,6 +418,10 @@ cmd_help() { echo " Builds the rootfs and guest kernel artifacts we use for our CI." echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands." echo "" + echo " download_ci_artifacts [--force]" + echo " Downloads the CI artifacts used for testing from our S3 bucket. If --force is passed, purges any existing" + echo " artifacts first. Useful for refreshing local artifacts after an update, or if something got messed up." + echo "" cat <]] @@ -555,6 +559,14 @@ cmd_distclean() { fi } +cmd_download_ci_artifacts() { + if [ "$1" = "--force" ]; then + rm -rf $FC_BUILD_DIR/img + fi + + ensure_ci_artifacts +} + ensure_ci_artifacts() { if ! command -v aws >/dev/null; then die "AWS CLI not installed, which is required for downloading artifacts for integration tests." From f3046829da6c6edf5a669d80d7e4e8c7f962cc58 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 28 Nov 2024 13:56:30 +0000 Subject: [PATCH 056/464] test: use pinned ami for m6i/6.1 This is to keep monitoring functionality and performance on the latest known stable AMI. Signed-off-by: Patrick Roy --- .buildkite/pipeline_perf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py index e8169bfb2cd..2a26f4277cc 100755 --- a/.buildkite/pipeline_perf.py +++ b/.buildkite/pipeline_perf.py @@ -124,6 +124,8 @@ pins = { # TODO: Unpin when performance instability on m6i/5.10 has gone. "linux_5.10-pinned": {"instance": "m6i.metal", "kv": "linux_5.10"}, + # TODO: Unpin when performance instability on m6i/6.1 has gone. + "linux_6.1-pinned": {"instance": "m6i.metal", "kv": "linux_6.1"}, } From 692c53d663a91abefcbb8f50dc5ffd550504f08d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 2 Dec 2024 15:31:26 +0000 Subject: [PATCH 057/464] devtool: stop asking for user confirmation on container pull Whenever devtool notices that its container is not cached locally, it requests user input to confirm the new devctr version should indeed be downloaded. In practice, I do not remember ever saying "no" here. On the other hand, forgetting to explicitly disable these confirmations in buildkite pipelines has lead to a myriad of "stuck pipeline" issues. Thus, remove this confirmation step altogether, as it does more harm than good. To avoid having to fix all pipelines that do pass `-y` today, simply treat the `-y` parameter as a no-op (suggested by Pablo, thanks!). We cannot remove get_user_confirmation altogether, as its also used by some of the release scripts, and there it seems like a valid usecase (but these scripts we never run in buildkite). Signed-off-by: Patrick Roy --- tools/devtool | 8 ++------ tools/functions | 5 ----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/tools/devtool b/tools/devtool index 4019a7f4b1e..36406c61bda 100755 --- a/tools/devtool +++ b/tools/devtool @@ -127,10 +127,6 @@ PRIV_KEY_PATH=/root/.ssh/id_rsa # Path to the linux kernel directory, as bind-mounted in the container. CTR_KERNEL_DIR="${CTR_FC_ROOT_DIR}/.kernel" -# Global options received by $0 -# These options are not command-specific, so we store them as global vars -OPT_UNATTENDED=false - # Get the target prefix to avoid repeated calls to uname -m TARGET_PREFIX="$(uname -m)-unknown-linux-" @@ -195,7 +191,6 @@ ensure_devctr() { # download it, if we don't. [[ $(docker images -q "$DEVCTR_IMAGE" | wc -l) -gt 0 ]] || { say "About to pull docker image $DEVCTR_IMAGE" - get_user_confirmation || die "Aborted." # Run docker pull 5 times in case it fails - sleep 3 seconds # between attempts @@ -1235,7 +1230,8 @@ main() { while [ $# -gt 0 ]; do case "$1" in -h|--help) { cmd_help; exit 1; } ;; - -y|--unattended) { OPT_UNATTENDED=true; } ;; + -y|--unattended) # purposefully ignored + ;; -*) die "Unknown arg: $1. Please use \`$0 help\` for help." ;; diff --git a/tools/functions b/tools/functions index 429a082d7a9..90e75c251bd 100644 --- a/tools/functions +++ b/tools/functions @@ -71,12 +71,7 @@ function SGR { # exit code 0 for successful confirmation # exit code != 0 if the user declined # -OPT_UNATTENDED=false get_user_confirmation() { - - # Pass if running unattended - [[ "$OPT_UNATTENDED" = true ]] && return 0 - # Fail if STDIN is not a terminal (there's no user to confirm anything) [[ -t 0 ]] || return 1 From d27e6978f5188ef973fad80c3d3c02c59317983f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:15:08 +0000 Subject: [PATCH 058/464] build(deps): Bump the firecracker group with 3 updates Bumps the firecracker group with 3 updates: [syn](https://github.com/dtolnay/syn), [indexmap](https://github.com/indexmap-rs/indexmap) and [libloading](https://github.com/nagisa/rust_libloading). Updates `syn` from 2.0.89 to 2.0.90 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.89...2.0.90) Updates `indexmap` from 2.6.0 to 2.7.0 - [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md) - [Commits](https://github.com/indexmap-rs/indexmap/compare/2.6.0...2.7.0) Updates `libloading` from 0.8.5 to 0.8.6 - [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.5...0.8.6) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: indexmap dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: libloading dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ src/clippy-tracing/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3fed9c404a..521552d3f87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,9 +739,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -862,9 +862,9 @@ checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -1316,9 +1316,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index f316fa884dc..e22cd6a1eae 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.21", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" -syn = { version = "2.0.89", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.90", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 660a7cbb7cd..2129df061f2 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] proc-macro2 = "1.0.92" quote = "1.0.37" -syn = { version = "2.0.89", features = ["full", "extra-traits"] } +syn = { version = "2.0.90", features = ["full", "extra-traits"] } [lints] workspace = true From 81bae9f8284abc2ab6778746bb60563d224c8025 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 2 Dec 2024 14:40:01 +0000 Subject: [PATCH 059/464] Add support for M7a in testing utils Add support for detection on m7a instance and prevent the test failure from missing cpu config test Signed-off-by: Jack Thomson --- tests/framework/utils_cpuid.py | 5 ++--- .../functional/test_cpu_features_x86_64.py | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py index 4303e3ba967..dabfb220240 100644 --- a/tests/framework/utils_cpuid.py +++ b/tests/framework/utils_cpuid.py @@ -25,6 +25,7 @@ class CpuModel(str, Enum): """CPU models""" AMD_MILAN = "AMD_MILAN" + AMD_GENOA = "AMD_GENOA" ARM_NEOVERSE_N1 = "ARM_NEOVERSE_N1" ARM_NEOVERSE_V1 = "ARM_NEOVERSE_V1" INTEL_SKYLAKE = "INTEL_SKYLAKE" @@ -39,9 +40,7 @@ class CpuModel(str, Enum): "Intel(R) Xeon(R) Platinum 8259CL CPU": "INTEL_CASCADELAKE", "Intel(R) Xeon(R) Platinum 8375C CPU": "INTEL_ICELAKE", }, - CpuVendor.AMD: { - "AMD EPYC 7R13": "AMD_MILAN", - }, + CpuVendor.AMD: {"AMD EPYC 7R13": "AMD_MILAN", "AMD EPYC 9R14": "AMD_GENOA"}, CpuVendor.ARM: {"0xd0c": "ARM_NEOVERSE_N1", "0xd40": "ARM_NEOVERSE_V1"}, } 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 23818ddc6b1..84d84bd8659 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -486,9 +486,14 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "hypervisor", "tsc_known_freq", } + case CpuModel.AMD_GENOA: + # Return here to allow the test to pass until CPU features to enable are confirmed + return case _: if os.environ.get("BUILDKITE") is not None: - assert False, f"Cpu model {cpu_model} is not supported" + assert ( + guest_feats == host_feats + ), f"Cpu model {cpu_model} is not supported" # From the `Intel® 64 Architecture x2APIC Specification` From 110e33087168170750639dbbb102f581a0fbadaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sun, 20 Oct 2024 13:36:58 +0200 Subject: [PATCH 060/464] tests: save metadata on snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is some information in the Microvm class that we don't save in the snapshot. Some tests do depend on those, so to make the booted/restored case homogenous, make room in the snapshot to save metadata that we can then restore. Signed-off-by: Pablo Barbáchano --- tests/framework/microvm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index ed02488bc7b..c1be701665a 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -75,6 +75,7 @@ class Snapshot: disks: dict ssh_key: Path snapshot_type: SnapshotType + meta: dict @property def is_diff(self) -> bool: @@ -110,6 +111,7 @@ def copy_to_chroot(self, chroot) -> "Snapshot": disks=self.disks, ssh_key=self.ssh_key, snapshot_type=self.snapshot_type, + meta=self.meta, ) @classmethod @@ -125,6 +127,7 @@ def load_from(cls, src: Path) -> "Snapshot": disks={dsk: src / p for dsk, p in obj["disks"].items()}, ssh_key=src / obj["ssh_key"], snapshot_type=SnapshotType(obj["snapshot_type"]), + meta=obj["meta"], ) def save_to(self, dst: Path): @@ -917,6 +920,9 @@ def make_snapshot( net_ifaces=[x["iface"] for ifname, x in self.iface.items()], ssh_key=self.ssh_key, snapshot_type=snapshot_type, + meta={ + "kernel_file": self.kernel_file, + }, ) def snapshot_diff(self, *, mem_path: str = "mem", vmstate_path="vmstate"): @@ -954,6 +960,9 @@ def restore_from_snapshot( if uffd_path is not None: mem_backend = {"backend_type": "Uffd", "backend_path": str(uffd_path)} + for key, value in snapshot.meta.items(): + setattr(self, key, value) + self.api.snapshot_load.put( mem_backend=mem_backend, snapshot_path=str(jailed_vmstate), From c2ebbb4d4d10538559d906b2108bb873f3bffb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sun, 20 Oct 2024 12:55:38 +0200 Subject: [PATCH 061/464] tests: refactor test_vulnerabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some further simplifications: - Simplify the "_host" tests as they will provide the same result in both A/B situations. - Add a second MicrovmFactory fixture with the "A" firecracker. - Add a uvm_any fixture that includes all CPU templates and also a boot/restored dimension. This decreases the need for separate tests. For example the guest test test_check_vulnerability_files_ab can now test all variants: 2 (restored/booted) * 3 (kernels) * 9 (cpu templates) = 54 tests Signed-off-by: Pablo Barbáchano --- tests/README.md | 12 +- tests/conftest.py | 35 ++ tests/framework/ab_test.py | 64 +-- tests/framework/microvm.py | 18 +- tests/framework/properties.py | 5 +- tests/framework/utils_cpu_templates.py | 4 +- .../integration_tests/functional/test_net.py | 43 +- .../security/test_vulnerabilities.py | 499 +++++------------- 8 files changed, 213 insertions(+), 467 deletions(-) diff --git a/tests/README.md b/tests/README.md index ea46ff56786..bf7aba9a547 100644 --- a/tests/README.md +++ b/tests/README.md @@ -306,10 +306,14 @@ that are pre-initialized with specific guest kernels and rootfs: 24.04 squashfs as rootfs, - `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel and the same Ubuntu 24.04 squashfs. - -Generally, tests should use the former if you are testing some interaction -between the guest and Firecracker, while the latter should be used if -Firecracker functionality unrelated to the guest is being tested. +- `uvm_any` yields started microvms, parametrized by all supported kernels, all + CPU templates (static, custom and none), and either booted or restored from a + snapshot. +- `uvm_any_booted` works the same as `uvm_any`, but only for booted VMs. + +Generally, tests should use `uvm_plain_any` if you are testing some interaction +between the guest and Firecracker, and `uvm_plain` should be used if Firecracker +functionality unrelated to the guest is being tested. ### Markers diff --git a/tests/conftest.py b/tests/conftest.py index 8f4c2e51ff5..5ad291d01a4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -459,3 +459,38 @@ def uvm_with_initrd( uvm = microvm_factory.build(guest_kernel_linux_5_10) uvm.initrd_file = fs yield uvm + + +def uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template): + """Return a booted uvm""" + uvm = microvm_factory.build(guest_kernel, rootfs) + uvm.spawn() + uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.set_cpu_template(cpu_template) + uvm.add_net_iface() + uvm.start() + return uvm + + +def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): + """Return a restored uvm""" + uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) + snapshot = uvm.snapshot_full() + uvm.kill() + uvm2 = microvm_factory.build() + uvm2.spawn() + uvm2.restore_from_snapshot(snapshot, resume=True) + uvm2.cpu_template_name = uvm.cpu_template_name + return uvm2 + + +@pytest.fixture(params=[uvm_booted, uvm_restored]) +def uvm_ctor(request): + """Fixture to return uvms with different constructors""" + return request.param + + +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): + """Return booted and restored uvms""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) diff --git a/tests/framework/ab_test.py b/tests/framework/ab_test.py index cf909d44fa6..2ef3e2350a7 100644 --- a/tests/framework/ab_test.py +++ b/tests/framework/ab_test.py @@ -21,7 +21,6 @@ of both invocations is the same, the test passes (with us being alerted to this situtation via a special pipeline that does not block PRs). If not, it fails, preventing PRs from introducing new vulnerable dependencies. """ -import os import statistics from pathlib import Path from tempfile import TemporaryDirectory @@ -31,14 +30,14 @@ from framework import utils from framework.defs import FC_WORKSPACE_DIR -from framework.microvm import Microvm +from framework.properties import global_props from framework.utils import CommandReturn from framework.with_filelock import with_filelock -from host_tools.cargo_build import DEFAULT_TARGET_DIR, get_firecracker_binaries +from host_tools.cargo_build import DEFAULT_TARGET_DIR # Locally, this will always compare against main, even if we try to merge into, say, a feature branch. # We might want to do a more sophisticated way to determine a "parent" branch here. -DEFAULT_A_REVISION = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") or "main" +DEFAULT_A_REVISION = global_props.buildkite_revision_a or "main" T = TypeVar("T") @@ -120,11 +119,6 @@ def binary_ab_test( return result_a, result_b, comparator(result_a, result_b) -def is_pr() -> bool: - """Returns `True` iff we are executing in the context of a build kite run on a pull request""" - return os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" - - def git_ab_test_host_command_if_pr( command: str, *, @@ -134,7 +128,7 @@ def git_ab_test_host_command_if_pr( """Runs the given bash command as an A/B-Test if we're in a pull request context (asserting that its stdout and stderr did not change across the PR). Otherwise runs the command, asserting it returns a zero exit code """ - if is_pr(): + if global_props.buildkite_pr: git_ab_test_host_command(command, comparator=comparator) return None @@ -176,56 +170,6 @@ def set_did_not_grow_comparator( ) -def precompiled_ab_test_guest_command( - microvm_factory: Callable[[Path, Path], Microvm], - command: str, - *, - comparator: Callable[[CommandReturn, CommandReturn], bool] = default_comparator, - a_revision: str = DEFAULT_A_REVISION, - b_revision: Optional[str] = None, -): - """The same as git_ab_test_command, but via SSH. The closure argument should setup a microvm using the passed - paths to firecracker and jailer binaries.""" - b_directory = ( - DEFAULT_B_DIRECTORY - if b_revision is None - else FC_WORKSPACE_DIR / "build" / b_revision - ) - - def test_runner(bin_dir, _is_a: bool): - microvm = microvm_factory(bin_dir / "firecracker", bin_dir / "jailer") - return microvm.ssh.run(command) - - (_, old_out, old_err), (_, new_out, new_err), the_same = binary_ab_test( - test_runner, - comparator, - a_directory=FC_WORKSPACE_DIR / "build" / a_revision, - b_directory=b_directory, - ) - - assert ( - the_same - ), f"The output of running command `{command}` changed:\nOld:\nstdout:\n{old_out}\nstderr\n{old_err}\n\nNew:\nstdout:\n{new_out}\nstderr:\n{new_err}" - - -def precompiled_ab_test_guest_command_if_pr( - microvm_factory: Callable[[Path, Path], Microvm], - command: str, - *, - comparator=default_comparator, - check_in_nonpr=True, -): - """The same as git_ab_test_command_if_pr, but via SSH""" - if is_pr(): - precompiled_ab_test_guest_command( - microvm_factory, command, comparator=comparator - ) - return None - - microvm = microvm_factory(*get_firecracker_binaries()) - return microvm.ssh.run(command, check=check_in_nonpr) - - def check_regression( a_samples: List[float], b_samples: List[float], *, n_resamples: int = 9999 ): diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index c1be701665a..832f56a877e 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -244,6 +244,7 @@ def __init__( self.disks_vhost_user = {} self.vcpus_count = None self.mem_size_bytes = None + self.cpu_template_name = None self._pre_cmd = [] if numa_node: @@ -735,12 +736,14 @@ def basic_config( smt=smt, mem_size_mib=mem_size_mib, track_dirty_pages=track_dirty_pages, - cpu_template=cpu_template, huge_pages=huge_pages, ) self.vcpus_count = vcpu_count self.mem_size_bytes = mem_size_mib * 2**20 + if cpu_template is not None: + self.set_cpu_template(cpu_template) + if self.memory_monitor: self.memory_monitor.start() @@ -773,6 +776,19 @@ def basic_config( if enable_entropy_device: self.enable_entropy_device() + def set_cpu_template(self, cpu_template): + """Set guest CPU template.""" + if cpu_template is None: + return + # static CPU template + if isinstance(cpu_template, str): + self.api.machine_config.patch(cpu_template=cpu_template) + self.cpu_template_name = cpu_template.lower() + # custom CPU template + elif isinstance(cpu_template, dict): + self.api.cpu_config.put(**cpu_template["template"]) + self.cpu_template_name = cpu_template["name"].lower() + def add_drive( self, drive_id, diff --git a/tests/framework/properties.py b/tests/framework/properties.py index b40df56249e..7dd1cb46588 100644 --- a/tests/framework/properties.py +++ b/tests/framework/properties.py @@ -72,11 +72,14 @@ def __init__(self): # major.minor.patch self.host_linux_patch = get_kernel_version(2) self.os = get_os_version() - self.host_os = get_host_os() + self.host_os = get_host_os() or "NA" self.libc_ver = "-".join(platform.libc_ver()) self.rust_version = run_cmd("rustc --version |awk '{print $2}'") + # Buildkite/PR information self.buildkite_pipeline_slug = os.environ.get("BUILDKITE_PIPELINE_SLUG") self.buildkite_build_number = os.environ.get("BUILDKITE_BUILD_NUMBER") + self.buildkite_pr = os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" + self.buildkite_revision_a = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") if self._in_git_repo(): self.git_commit_id = run_cmd("git rev-parse HEAD") diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index e57ecfe72c7..89326c1da5a 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -3,6 +3,8 @@ """Utilities for CPU template related functionality.""" +# pylint:disable=too-many-return-statements + import json from pathlib import Path @@ -23,9 +25,7 @@ def get_supported_cpu_templates(): """ Return the list of CPU templates supported by the platform. """ - # pylint:disable=too-many-return-statements host_linux = global_props.host_linux_version_tpl - match get_cpu_vendor(), global_props.cpu_codename: # T2CL template is only supported on Cascade Lake and newer CPUs. case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index a804b8f90a8..2072d015ca2 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -84,14 +84,23 @@ def test_multi_queue_unsupported(uvm_plain): ) -def run_udp_offload_test(vm): +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs): + """Return booted and restored uvm with no CPU templates""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, None) + + +def test_tap_offload(uvm_any): """ + Verify that tap offload features are configured for a booted/restored VM. + - Start a socat UDP server in the guest. - Try to send a UDP message with UDP offload enabled. If tap offload features are not configured, an attempt to send a message will fail with EIO "Input/output error". More info (search for "TUN_F_CSUM is a must"): https://blog.cloudflare.com/fr-fr/virtual-networking-101-understanding-tap/ """ + vm = uvm_any port = "81" out_filename = "/tmp/out.txt" message = "x" @@ -112,35 +121,3 @@ def run_udp_offload_test(vm): # Check that the server received the message ret = vm.ssh.run(f"cat {out_filename}") assert ret.stdout == message, f"{ret.stdout=} {ret.stderr=}" - - -def test_tap_offload_booted(uvm_plain_any): - """ - Verify that tap offload features are configured for a booted VM. - """ - vm = uvm_plain_any - vm.spawn() - vm.basic_config() - vm.add_net_iface() - vm.start() - - run_udp_offload_test(vm) - - -def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs): - """ - Verify that tap offload features are configured for a restored VM. - """ - src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - src.spawn() - src.basic_config() - src.add_net_iface() - src.start() - snapshot = src.snapshot_full() - src.kill() - - dst = microvm_factory.build() - dst.spawn() - dst.restore_from_snapshot(snapshot, resume=True) - - run_udp_offload_test(dst) diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index fed9dbc96d7..a4461aded78 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -5,21 +5,17 @@ # script from the third party "Spectre & Meltdown Checker" project. This script is under the # GPL-3.0-only license. """Tests vulnerabilities mitigations.""" + import json -import os +from pathlib import Path import pytest import requests from framework import utils -from framework.ab_test import ( - is_pr, - precompiled_ab_test_guest_command, - precompiled_ab_test_guest_command_if_pr, - set_did_not_grow_comparator, -) +from framework.ab_test import git_clone +from framework.microvm import MicroVMFactory from framework.properties import global_props -from framework.utils import CommandReturn CHECKER_URL = "https://meltdown.ovh" CHECKER_FILENAME = "spectre-meltdown-checker.sh" @@ -29,119 +25,71 @@ VULN_DIR = "/sys/devices/system/cpu/vulnerabilities" -def configure_microvm( - factory, - kernel, - rootfs, - *, - firecracker=None, - jailer=None, - cpu_template=None, - custom_cpu_template=None, -): - """Build a microvm for vulnerability tests""" - assert not (cpu_template and custom_cpu_template) - # Either both or neither are specified - assert firecracker and jailer or not firecracker and not jailer - - if firecracker: - microvm = factory.build( - kernel, rootfs, fc_binary_path=firecracker, jailer_binary_path=jailer - ) - else: - microvm = factory.build(kernel, rootfs) - - microvm.spawn() - microvm.basic_config(vcpu_count=2, mem_size_mib=256, cpu_template=cpu_template) - if custom_cpu_template: - microvm.api.cpu_config.put(**custom_cpu_template["template"]) - microvm.cpu_template = cpu_template - if cpu_template is None and custom_cpu_template is not None: - microvm.cpu_template = custom_cpu_template["name"] - microvm.add_net_iface() - microvm.start() - return microvm +class SpectreMeltdownChecker: + """Helper class to use Spectre & Meltdown Checker""" + def __init__(self, path): + self.path = path -@pytest.fixture -def build_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, -): - """Fixture returning a factory function for a normal microvm""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - ) - - -@pytest.fixture -def build_microvm_with_template( - microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template -): - """Fixture returning a factory function for microvms with our built-in template""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - cpu_template=cpu_template, - ) - - -@pytest.fixture -def build_microvm_with_custom_template( - microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template -): - """Fixture returning a factory function for microvms with custom cpu templates""" - return lambda firecracker=None, jailer=None: configure_microvm( - microvm_factory, - guest_kernel_linux_5_10, - rootfs, - firecracker=firecracker, - jailer=jailer, - custom_cpu_template=custom_cpu_template, - ) - - -def with_restore(factory, microvm_factory): - """Turns the given microvm factory into one that makes the microvm go through a snapshot-restore cycle""" - - def restore(firecracker=None, jailer=None): - microvm = factory(firecracker, jailer) - - snapshot = microvm.snapshot_full() - - if firecracker: - dst_vm = microvm_factory.build( - fc_binary_path=firecracker, jailer_binary_path=jailer - ) - else: - dst_vm = microvm_factory.build() - dst_vm.spawn() - # Restore the destination VM from the snapshot - dst_vm.restore_from_snapshot(snapshot, resume=True) - dst_vm.cpu_template = microvm.cpu_template - - return dst_vm - - return restore - - -def with_checker(factory, spectre_meltdown_checker): - """Turns the given microvm factory function into one that also contains the spectre-meltdown checker script""" + def _parse_output(self, output): + return { + json.dumps(entry) # dict is unhashable + for entry in json.loads(output) + if entry["VULNERABLE"] + } - def download_checker(firecracker, jailer): - microvm = factory(firecracker, jailer) - microvm.ssh.scp_put(spectre_meltdown_checker, REMOTE_CHECKER_PATH) - return microvm + def get_report_for_guest(self, vm) -> set: + """Parses the output of `spectre-meltdown-checker.sh --batch json` + and returns the set of issues for which it reported 'Vulnerable'. - return download_checker + Sample stdout: + ``` + [ + { + "NAME": "SPECTRE VARIANT 1", + "CVE": "CVE-2017-5753", + "VULNERABLE": false, + "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization" + }, + { ... } + ] + ``` + """ + vm.ssh.scp_put(self.path, REMOTE_CHECKER_PATH) + res = vm.ssh.run(REMOTE_CHECKER_COMMAND) + return self._parse_output(res.stdout) + + def get_report_for_host(self) -> set: + """Runs `spectre-meltdown-checker.sh` in the host and returns the set of + issues for which it reported 'Vulnerable'. + """ + + res = utils.check_output(f"sh {self.path} --batch json") + return self._parse_output(res.stdout) + + def expected_vulnerabilities(self, cpu_template_name): + """ + There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh + script is run inside the guest from below the tests: + test_spectre_meltdown_checker_on_guest and + test_spectre_meltdown_checker_on_restored_guest + The same script when run on host doesn't report the + exception which means the instances are actually not vulnerable to REPTAR. + The only reason why the script cannot determine if the guest + is vulnerable or not because Firecracker does not expose the microcode + version to the guest. + + The check in spectre_meltdown_checker is here: + https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637 + + Since we have a test on host and the exception in guest is not valid, + we add a check to ignore this exception. + """ + if global_props.cpu_codename == "INTEL_ICELAKE" and cpu_template_name is None: + return { + '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}' + } + return set() @pytest.fixture(scope="session", name="spectre_meltdown_checker") @@ -149,189 +97,32 @@ def download_spectre_meltdown_checker(tmp_path_factory): """Download spectre / meltdown checker script.""" resp = requests.get(CHECKER_URL, timeout=5) resp.raise_for_status() - path = tmp_path_factory.mktemp("tmp", True) / CHECKER_FILENAME path.write_bytes(resp.content) - - return path - - -def spectre_meltdown_reported_vulnerablities( - spectre_meltdown_checker_output: CommandReturn, -) -> set: - """ - Parses the output of `spectre-meltdown-checker.sh --batch json` and returns the set of issues - for which it reported 'Vulnerable'. - - Sample stdout: - ``` - [ - { - "NAME": "SPECTRE VARIANT 1", - "CVE": "CVE-2017-5753", - "VULNERABLE": false, - "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization" - }, - { - ... - } - ] - ``` - """ - return { - json.dumps(entry) # dict is unhashable - for entry in json.loads(spectre_meltdown_checker_output.stdout) - if entry["VULNERABLE"] - } - - -def check_vulnerabilities_on_guest(status): - """ - There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh - script is run inside the guest from below the tests: - test_spectre_meltdown_checker_on_guest and - test_spectre_meltdown_checker_on_restored_guest - The same script when run on host doesn't report the - exception which means the instances are actually not vulnerable to REPTAR. - The only reason why the script cannot determine if the guest - is vulnerable or not because Firecracker does not expose the microcode - version to the guest. - - The check in spectre_meltdown_checker is here: - https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637 - - Since we have a test on host and the exception in guest is not valid, - we add a check to ignore this exception. - """ - report_guest_vulnerabilities = spectre_meltdown_reported_vulnerablities(status) - known_guest_vulnerabilities = set() - if global_props.cpu_codename == "INTEL_ICELAKE": - known_guest_vulnerabilities = { - '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}' - } - assert report_guest_vulnerabilities == known_guest_vulnerabilities + return SpectreMeltdownChecker(path) # Nothing can be sensibly tested in a PR context here @pytest.mark.skipif( - is_pr(), reason="Test depends solely on factors external to GitHub repository" + global_props.buildkite_pr, + reason="Test depends solely on factors external to GitHub repository", ) def test_spectre_meltdown_checker_on_host(spectre_meltdown_checker): - """ - Test with the spectre / meltdown checker on host. - """ - rc, output, _ = utils.run_cmd(f"sh {spectre_meltdown_checker} --batch json") - - if output and rc != 0: - report = spectre_meltdown_reported_vulnerablities(output) - expected = {} - assert report == expected, f"Unexpected vulnerabilities: {report} vs {expected}" - - -def test_spectre_meltdown_checker_on_guest(spectre_meltdown_checker, build_microvm): - """ - Test with the spectre / meltdown checker on guest. - """ - - status = precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - check_in_nonpr=False, - ) - if status and status.returncode != 0: - check_vulnerabilities_on_guest(status) - - -def test_spectre_meltdown_checker_on_restored_guest( - spectre_meltdown_checker, build_microvm, microvm_factory -): - """ - Test with the spectre / meltdown checker on a restored guest. - """ - status = precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm, microvm_factory), spectre_meltdown_checker - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - check_in_nonpr=False, - ) - if status and status.returncode != 0: - check_vulnerabilities_on_guest(status) - - -def test_spectre_meltdown_checker_on_guest_with_template( - spectre_meltdown_checker, build_microvm_with_template -): - """ - Test with the spectre / meltdown checker on guest with CPU template. - """ + """Test with the spectre / meltdown checker on host.""" + report = spectre_meltdown_checker.get_report_for_host() + assert report == set(), f"Unexpected vulnerabilities: {report}" - precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm_with_template, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - -def test_spectre_meltdown_checker_on_guest_with_custom_template( - spectre_meltdown_checker, build_microvm_with_custom_template -): - """ - Test with the spectre / meltdown checker on guest with a custom CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker(build_microvm_with_custom_template, spectre_meltdown_checker), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - - -def test_spectre_meltdown_checker_on_restored_guest_with_template( - spectre_meltdown_checker, build_microvm_with_template, microvm_factory -): - """ - Test with the spectre / meltdown checker on a restored guest with a CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm_with_template, microvm_factory), - spectre_meltdown_checker, - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) - - -def test_spectre_meltdown_checker_on_restored_guest_with_custom_template( - spectre_meltdown_checker, - build_microvm_with_custom_template, - microvm_factory, -): - """ - Test with the spectre / meltdown checker on a restored guest with a custom CPU template. - """ - precompiled_ab_test_guest_command_if_pr( - with_checker( - with_restore(build_microvm_with_custom_template, microvm_factory), - spectre_meltdown_checker, - ), - REMOTE_CHECKER_COMMAND, - comparator=set_did_not_grow_comparator( - spectre_meltdown_reported_vulnerablities - ), - ) +# Nothing can be sensibly tested here in a PR context +@pytest.mark.skipif( + global_props.buildkite_pr, + reason="Test depends solely on factors external to GitHub repository", +) +def test_vulnerabilities_on_host(): + """Test vulnerability files on host.""" + res = utils.run_cmd(f"grep -r Vulnerable {VULN_DIR}") + # if grep finds no matching lines, it exits with status 1 + assert res.returncode == 1, res.stdout def get_vuln_files_exception_dict(template): @@ -372,25 +163,14 @@ def get_vuln_files_exception_dict(template): # 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": + 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": + elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "t2s": exception_dict["mmio_stale_data"] = "Clear CPU buffers" return exception_dict -# Nothing can be sensibly tested here in a PR context -@pytest.mark.skipif( - is_pr(), reason="Test depends solely on factors external to GitHub repository" -) -def test_vulnerabilities_on_host(): - """ - Test vulnerabilities files on host. - """ - utils.check_output(f"! grep -r Vulnerable {VULN_DIR}") - - def check_vulnerabilities_files_on_guest(microvm): """ Check that the guest's vulnerabilities files do not contain `Vulnerable`. @@ -400,88 +180,75 @@ def check_vulnerabilities_files_on_guest(microvm): # Retrieve a list of vulnerabilities files available inside guests. vuln_dir = "/sys/devices/system/cpu/vulnerabilities" _, stdout, _ = microvm.ssh.check_output(f"find -D all {vuln_dir} -type f") - vuln_files = stdout.split("\n") + vuln_files = stdout.splitlines() # Fixtures in this file (test_vulnerabilities.py) add this special field. - template = microvm.cpu_template + template = microvm.cpu_template_name # Check that vulnerabilities files in the exception dictionary have the expected values and # the others do not contain "Vulnerable". exceptions = get_vuln_files_exception_dict(template) + results = [] for vuln_file in vuln_files: - filename = os.path.basename(vuln_file) + filename = Path(vuln_file).name if filename in exceptions: - _, stdout, _ = microvm.ssh.run(f"cat {vuln_file}") + _, stdout, _ = microvm.ssh.check_output(f"cat {vuln_file}") assert exceptions[filename] in stdout else: cmd = f"grep Vulnerable {vuln_file}" - ecode, stdout, stderr = microvm.ssh.run(cmd) - assert ecode == 1, f"{vuln_file}: stdout:\n{stdout}\nstderr:\n{stderr}\n" - - -def check_vulnerabilities_files_ab(builder): - """Does an A/B test on the contents of the /sys/devices/system/cpu/vulnerabilities files in the guest if - running in a PR pipeline, and otherwise calls `check_vulnerabilities_files_on_guest` - """ - if is_pr(): - precompiled_ab_test_guest_command( - builder, - f"! grep -r Vulnerable {VULN_DIR}", - comparator=set_did_not_grow_comparator( - lambda output: set(output.stdout.splitlines()) - ), - ) - else: - check_vulnerabilities_files_on_guest(builder()) + _ecode, stdout, _stderr = microvm.ssh.run(cmd) + results.append({"file": vuln_file, "stdout": stdout}) + return results -def test_vulnerabilities_files_on_guest(build_microvm): - """ - Test vulnerabilities files on guest. - """ - check_vulnerabilities_files_ab(build_microvm) - - -def test_vulnerabilities_files_on_restored_guest(build_microvm, microvm_factory): - """ - Test vulnerabilities files on a restored guest. - """ - check_vulnerabilities_files_ab(with_restore(build_microvm, microvm_factory)) +@pytest.fixture +def microvm_factory_a(record_property): + """MicroVMFactory using revision A binaries""" + revision_a = global_props.buildkite_revision_a + bin_dir = git_clone(Path("../build") / revision_a, revision_a).resolve() + fc_bin = bin_dir / "firecracker" + jailer_bin = bin_dir / "jailer" + record_property("firecracker_bin", str(fc_bin)) + uvm_factory = MicroVMFactory(fc_bin, jailer_bin) + yield uvm_factory + uvm_factory.kill() -def test_vulnerabilities_files_on_guest_with_template(build_microvm_with_template): - """ - Test vulnerabilities files on guest with CPU template. - """ - check_vulnerabilities_files_ab(build_microvm_with_template) - +@pytest.fixture +def uvm_any_a(microvm_factory_a, uvm_ctor, guest_kernel, rootfs, cpu_template_any): + """Return uvm with revision A firecracker -def test_vulnerabilities_files_on_guest_with_custom_template( - build_microvm_with_custom_template, -): + Since pytest caches fixtures, this guarantees uvm_any_a will match a vm from uvm_any. + See https://docs.pytest.org/en/stable/how-to/fixtures.html#fixtures-can-be-requested-more-than-once-per-test-return-values-are-cached """ - Test vulnerabilities files on guest with a custom CPU template. - """ - check_vulnerabilities_files_ab(build_microvm_with_custom_template) + return uvm_ctor(microvm_factory_a, guest_kernel, rootfs, cpu_template_any) -def test_vulnerabilities_files_on_restored_guest_with_template( - build_microvm_with_template, microvm_factory -): - """ - Test vulnerabilities files on a restored guest with a CPU template. - """ - check_vulnerabilities_files_ab( - with_restore(build_microvm_with_template, microvm_factory) - ) +def test_check_vulnerability_files_ab(request, uvm_any): + """Test vulnerability files on guests""" + res_b = check_vulnerabilities_files_on_guest(uvm_any) + if global_props.buildkite_pr: + # we only get the uvm_any_a fixtures if we need it + uvm_a = request.getfixturevalue("uvm_any_a") + res_a = check_vulnerabilities_files_on_guest(uvm_a) + assert res_b <= res_a + else: + assert not [x for x in res_b if "Vulnerable" in x["stdout"]] -def test_vulnerabilities_files_on_restored_guest_with_custom_template( - build_microvm_with_custom_template, microvm_factory +def test_spectre_meltdown_checker_on_guest( + request, + uvm_any, + spectre_meltdown_checker, ): - """ - Test vulnerabilities files on a restored guest with a custom CPU template. - """ - check_vulnerabilities_files_ab( - with_restore(build_microvm_with_custom_template, microvm_factory) - ) + """Test with the spectre / meltdown checker on any supported guest.""" + res_b = spectre_meltdown_checker.get_report_for_guest(uvm_any) + if global_props.buildkite_pr: + # we only get the uvm_any_a fixtures if we need it + uvm_a = request.getfixturevalue("uvm_any_a") + res_a = spectre_meltdown_checker.get_report_for_guest(uvm_a) + assert res_b <= res_a + else: + assert res_b == spectre_meltdown_checker.expected_vulnerabilities( + uvm_any.cpu_template_name + ) From 1882a3da67ecb06ebf19fe9b4a9b3701edd6d323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 31 Oct 2024 22:49:26 +0100 Subject: [PATCH 062/464] tests: refactor test_nv.py to use uvm_any_booted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a new uvm_any_booted fixture to make the test simpler. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 6 +++++ tests/integration_tests/security/test_nv.py | 30 +++------------------ 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5ad291d01a4..a2990a56c98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -494,3 +494,9 @@ def uvm_ctor(request): def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): """Return booted and restored uvms""" return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) + + +@pytest.fixture +def uvm_any_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any): + """Return booted uvms""" + return uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any) diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py index 5dd5acb2308..73f042d5ae3 100644 --- a/tests/integration_tests/security/test_nv.py +++ b/tests/integration_tests/security/test_nv.py @@ -16,31 +16,7 @@ start providing the feature by mistake. """ -import pytest - -@pytest.fixture -def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any): - """A microvm fixture parametrized with all possible templates""" - vm = microvm_factory.build(guest_kernel, rootfs) - vm.spawn() - cpu_template = None - if isinstance(cpu_template_any, str): - cpu_template = cpu_template_any - vm.basic_config(cpu_template=cpu_template) - if isinstance(cpu_template_any, dict): - vm.api.cpu_config.put(**cpu_template_any["template"]) - vm.add_net_iface() - vm.start() - yield vm - - -def test_no_nv_when_using_cpu_templates(uvm_with_cpu_template): - """ - Double-check that guests using CPU templates don't have Nested Virtualization - enabled. - """ - - vm = uvm_with_cpu_template - rc, _, _ = vm.ssh.run("[ ! -e /dev/kvm ]") - assert rc == 0, "/dev/kvm exists" +def test_no_nested_virtualization(uvm_any_booted): + """Validate that guests don't have Nested Virtualization enabled.""" + uvm_any_booted.ssh.check_output("[ ! -e /dev/kvm ]") From 033402e7147118539d7379ba11d1881ec42911bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 29 Oct 2024 16:06:17 +0100 Subject: [PATCH 063/464] tests: refactor test_cpu_features_aarch64 to use uvm_any MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new uvm_any fixture to make the tests simpler Signed-off-by: Pablo Barbáchano --- tests/framework/utils_cpu_templates.py | 10 +- .../functional/test_cpu_features_aarch64.py | 157 ++++-------------- 2 files changed, 34 insertions(+), 133 deletions(-) diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 89326c1da5a..56021a21aaa 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -22,9 +22,7 @@ def get_supported_cpu_templates(): - """ - Return the list of CPU templates supported by the platform. - """ + """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: # T2CL template is only supported on Cascade Lake and newer CPUs. @@ -44,12 +42,8 @@ def get_supported_cpu_templates(): def get_supported_custom_cpu_templates(): - """ - Return the list of custom CPU templates supported by the platform. - """ - # pylint:disable=too-many-return-statements + """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: # T2CL template is only supported on Cascade Lake and newer CPUs. case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 8357f54b568..1edcb39f151 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -3,83 +3,63 @@ """Tests for the CPU features for aarch64.""" import os -import platform -import re import pytest -import framework.utils_cpuid as cpuid_utils from framework import utils from framework.properties import global_props from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel -PLATFORM = platform.machine() +pytestmark = pytest.mark.skipif( + global_props.cpu_architecture != "aarch64", reason="Only run in aarch64" +) -DEFAULT_G2_FEATURES = set( +G2_FEATS = set( ( "fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp " "asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs" - ).split(" ") + ).split() ) -DEFAULT_G3_FEATURES_5_10 = DEFAULT_G2_FEATURES | set( - "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split( - " " - ) +G3_FEATS = G2_FEATS | set( + "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split() ) -DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10 = DEFAULT_G3_FEATURES_5_10 | set( - "paca pacg sve svebf16 svei8mm".split(" ") -) +G3_SVE_AND_PAC = set("paca pacg sve svebf16 svei8mm".split()) -DEFAULT_G3_FEATURES_V1N1 = DEFAULT_G2_FEATURES +def test_guest_cpu_features(uvm_any): + """Check the CPU features for a microvm with different CPU templates""" -def _check_cpu_features_arm(test_microvm, guest_kv, template_name=None): - expected_cpu_features = {"Flags": []} - match cpuid_utils.get_cpu_model_name(), guest_kv, template_name: - case CpuModel.ARM_NEOVERSE_N1, _, "v1n1": - expected_cpu_features = DEFAULT_G2_FEATURES - case CpuModel.ARM_NEOVERSE_N1, _, None: - expected_cpu_features = DEFAULT_G2_FEATURES + vm = uvm_any + expected_cpu_features = set() + match global_props.cpu_model, vm.cpu_template_name: + case CpuModel.ARM_NEOVERSE_N1, "v1n1": + expected_cpu_features = G2_FEATS + case CpuModel.ARM_NEOVERSE_N1, None: + expected_cpu_features = G2_FEATS # [cm]7g with guest kernel 5.10 and later - case CpuModel.ARM_NEOVERSE_V1, _, "v1n1": - expected_cpu_features = DEFAULT_G3_FEATURES_V1N1 - case CpuModel.ARM_NEOVERSE_V1, _, "aarch64_with_sve_and_pac": - expected_cpu_features = DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10 - case CpuModel.ARM_NEOVERSE_V1, _, None: - expected_cpu_features = DEFAULT_G3_FEATURES_5_10 - - _, stdout, _ = test_microvm.ssh.check_output(CPU_FEATURES_CMD) - flags = set(stdout.strip().split(" ")) - assert flags == expected_cpu_features + case CpuModel.ARM_NEOVERSE_V1, "v1n1": + expected_cpu_features = G2_FEATS + case CpuModel.ARM_NEOVERSE_V1, "aarch64_with_sve_and_pac": + expected_cpu_features = G3_FEATS | G3_SVE_AND_PAC + case CpuModel.ARM_NEOVERSE_V1, None: + expected_cpu_features = G3_FEATS + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + assert guest_feats == expected_cpu_features -def get_cpu_template_dir(cpu_template): - """ - Utility function to return a valid string which will be used as - name of the directory where snapshot artifacts are stored during - snapshot test and loaded from during restore test. - """ - return cpu_template if cpu_template else "none" - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_host_vs_guest_cpu_features_aarch64(uvm_nano): +def test_host_vs_guest_cpu_features(uvm_nano): """Check CPU features host vs guest""" vm = uvm_nano vm.add_net_iface() vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - - cpu_model = cpuid_utils.get_cpu_model_name() + host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + cpu_model = global_props.cpu_model match cpu_model: case CpuModel.ARM_NEOVERSE_N1: expected_guest_minus_host = set() @@ -141,79 +121,6 @@ def test_host_vs_guest_cpu_features_aarch64(uvm_nano): assert guest_feats - host_feats == expected_guest_minus_host case _: if os.environ.get("BUILDKITE") is not None: - assert False, f"Cpu model {cpu_model} is not supported" - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_default_cpu_features(microvm_factory, guest_kernel, rootfs): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config() - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv) - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_cpu_features_with_static_template( - microvm_factory, guest_kernel, rootfs, cpu_template -): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config(cpu_template=cpu_template) - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv, "v1n1") - - # Check that cpu features are still correct - # after snap/restore cycle. - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) - _check_cpu_features_arm(restored_vm, guest_kv, "v1n1") - - -@pytest.mark.skipif( - PLATFORM != "aarch64", - reason="This is aarch64 specific test.", -) -def test_cpu_features_with_custom_template( - microvm_factory, guest_kernel, rootfs, custom_cpu_template -): - """ - Check the CPU features for a microvm with the specified config. - """ - - vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False) - vm.spawn() - vm.basic_config() - vm.api.cpu_config.put(**custom_cpu_template["template"]) - vm.add_net_iface() - vm.start() - guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1) - _check_cpu_features_arm(vm, guest_kv, custom_cpu_template["name"]) - - # Check that cpu features are still correct - # after snap/restore cycle. - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) - _check_cpu_features_arm(restored_vm, guest_kv, custom_cpu_template["name"]) + assert ( + False + ), f"Cpu model {cpu_model} is not supported, please onboard it." From da969fb7615a74cc1447d24decc74988a3a9b307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 22:31:29 +0100 Subject: [PATCH 064/464] tests: skip x86_64 tests at module level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All tests in the file are x86_64 specific, so do the skip at the top-level, once. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_x86_64.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) 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 84d84bd8659..bb86df2eade 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -30,6 +30,10 @@ ) DATA_FILES = Path("./data/msr") +pytestmark = pytest.mark.skipif( + global_props.cpu_architecture != "x86_64", reason="Only run in x86_64" +) + def read_msr_csv(fd): """Read a CSV of MSRs""" @@ -105,7 +109,6 @@ def skip_test_based_on_artifacts(snapshot_artifacts_dir): pytest.skip(re.sub(" +", " ", reason)) -@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.") @pytest.mark.parametrize( "num_vcpus", [1, 2, 16], @@ -126,7 +129,6 @@ def test_cpuid(uvm_plain_any, num_vcpus, htt): _check_cpuid_x86(vm, num_vcpus, "true" if num_vcpus > 1 else "false") -@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.") @pytest.mark.skipif( cpuid_utils.get_cpu_vendor() != cpuid_utils.CpuVendor.AMD, reason="L3 cache info is only present in 0x80000006 for AMD", @@ -143,9 +145,6 @@ def test_extended_cache_features(uvm_plain_any): _check_extended_cache_features(vm) -@pytest.mark.skipif( - PLATFORM != "x86_64", reason="The CPU brand string is masked only on x86_64." -) def test_brand_string(uvm_plain_any): """ Ensure good formatting for the guest brand string. @@ -204,10 +203,6 @@ def test_brand_string(uvm_plain_any): assert False -@pytest.mark.skipif( - PLATFORM != "x86_64", - reason="This is x86_64 specific test.", -) def test_host_vs_guest_cpu_features_x86_64(uvm_nano): """Check CPU features host vs guest""" @@ -929,9 +924,6 @@ def test_cpu_cpuid_restore(microvm_factory, guest_kernel, msr_cpu_template): ) -@pytest.mark.skipif( - PLATFORM != "x86_64", reason="CPU features are masked only on x86_64." -) @pytest.mark.parametrize("cpu_template", ["T2", "T2S", "C3"]) def test_cpu_template(uvm_plain_any, cpu_template, microvm_factory): """ @@ -1249,7 +1241,6 @@ def check_enabled_features(test_microvm, cpu_template): ) -@pytest.mark.skipif(PLATFORM != "x86_64", reason="This test is specific to x86_64.") def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): """ This test verifies that the warning message about MMIO stale data mitigation From 409877aed9e7d29962ff399e13b55bc463d7a9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 22:32:55 +0100 Subject: [PATCH 065/464] tests: refactor test_cpu_features_x86_64.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the common feature flags to get some clarity on what are the differences between the CPUs. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_x86_64.py | 203 +++++------------- 1 file changed, 56 insertions(+), 147 deletions(-) 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 bb86df2eade..f8bbe1ef52e 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -203,6 +203,57 @@ def test_brand_string(uvm_plain_any): assert False +INTEL_HOST_ONLY_FEATS = { + "acpi", + "aperfmperf", + "arch_perfmon", + "art", + "bts", + "cat_l3", + "cdp_l3", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "dca", + "ds_cpl", + "dtes64", + "dtherm", + "dts", + "epb", + "ept", + "ept_ad", + "est", + "flexpriority", + "flush_l1d", + "hwp", + "hwp_act_window", + "hwp_epp", + "hwp_pkg_req", + "ida", + "intel_ppin", + "intel_pt", + "mba", + "monitor", + "pbe", + "pdcm", + "pebs", + "pln", + "pts", + "rdt_a", + "sdbg", + "smx", + "tm", + "tm2", + "tpr_shadow", + "vmx", + "vnmi", + "vpid", + "xtpr", +} + + def test_host_vs_guest_cpu_features_x86_64(uvm_nano): """Check CPU features host vs guest""" @@ -283,110 +334,14 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): "tsc_known_freq", } case CpuModel.INTEL_SKYLAKE: - assert host_feats - guest_feats == { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", - } + assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS assert guest_feats - host_feats == { "hypervisor", "tsc_known_freq", "umip", } case CpuModel.INTEL_CASCADELAKE: - expected_host_minus_guest = { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", - } + expected_host_minus_guest = INTEL_HOST_ONLY_FEATS expected_guest_minus_host = { "hypervisor", "tsc_known_freq", @@ -414,56 +369,10 @@ def test_host_vs_guest_cpu_features_x86_64(uvm_nano): assert host_feats - guest_feats == expected_host_minus_guest assert guest_feats - host_feats == expected_guest_minus_host case CpuModel.INTEL_ICELAKE: - host_guest_diff_5_10 = { - "dtes64", - "hwp_act_window", - "pdcm", - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", + host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { "pconfig", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "split_lock_detect", - "tm", - "tm2", "tme", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", + "split_lock_detect", } host_guest_diff_6_1 = host_guest_diff_5_10 - { "bts", @@ -1261,7 +1170,7 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): "does not apply the mitigation against MMIO stale data " "vulnerability." ) - if cpu_template == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE": + if uvm.cpu_template_name == "c3" and global_props.cpu_codename == "INTEL_SKYLAKE": assert message in uvm.log_data else: assert message not in uvm.log_data From f4f7536eae69dce49895b476b0e58fa8fc597b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 18 Nov 2024 23:10:09 +0100 Subject: [PATCH 066/464] tests: move host vs guest cpu features into a single test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the same test spread over two files. Putting it together in a new file so they don't drift over time. Signed-off-by: Pablo Barbáchano --- .../functional/test_cpu_features_aarch64.py | 78 ----- .../test_cpu_features_host_vs_guest.py | 272 ++++++++++++++++++ .../functional/test_cpu_features_x86_64.py | 198 ------------- 3 files changed, 272 insertions(+), 276 deletions(-) create mode 100644 tests/integration_tests/functional/test_cpu_features_host_vs_guest.py diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 1edcb39f151..2068194a894 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -2,11 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 """Tests for the CPU features for aarch64.""" -import os - import pytest -from framework import utils from framework.properties import global_props from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel @@ -49,78 +46,3 @@ def test_guest_cpu_features(uvm_any): guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) assert guest_feats == expected_cpu_features - - -def test_host_vs_guest_cpu_features(uvm_nano): - """Check CPU features host vs guest""" - - vm = uvm_nano - vm.add_net_iface() - vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) - cpu_model = global_props.cpu_model - match cpu_model: - case CpuModel.ARM_NEOVERSE_N1: - expected_guest_minus_host = set() - expected_host_minus_guest = set() - - # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since - # they have an errata whereby an MSR to the SSBS special-purpose register does not - # affect subsequent speculative instructions, permitting speculative store bypassing for - # a window of time. - # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 - # - # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test - # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. - host_has_ssbs = global_props.host_os not in { - "amzn2", - "amzn2023", - } and global_props.host_linux_version_tpl < (6, 11) - guest_has_ssbs = vm.guest_kernel_version < (6, 11) - - if host_has_ssbs and not guest_has_ssbs: - expected_host_minus_guest |= {"ssbs"} - if not host_has_ssbs and guest_has_ssbs: - expected_guest_minus_host |= {"ssbs"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case CpuModel.ARM_NEOVERSE_V1: - expected_guest_minus_host = set() - # KVM does not enable PAC or SVE features by default - # and Firecracker does not enable them either. - expected_host_minus_guest = { - "paca", - "pacg", - "sve", - "svebf16", - "svei8mm", - } - - # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since - # they have an errata whereby an MSR to the SSBS special-purpose register does not - # affect subsequent speculative instructions, permitting speculative store bypassing for - # a window of time. - # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 - # - # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test - # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. - host_has_ssbs = global_props.host_os not in { - "amzn2", - "amzn2023", - } and global_props.host_linux_version_tpl < (6, 11) - guest_has_ssbs = vm.guest_kernel_version < (6, 11) - - if host_has_ssbs and not guest_has_ssbs: - expected_host_minus_guest |= {"ssbs"} - if not host_has_ssbs and guest_has_ssbs: - expected_guest_minus_host |= {"ssbs"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case _: - if os.environ.get("BUILDKITE") is not None: - assert ( - False - ), f"Cpu model {cpu_model} is not supported, please onboard it." 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 new file mode 100644 index 00000000000..bbf4ed57d21 --- /dev/null +++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py @@ -0,0 +1,272 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# pylint: disable=too-many-statements + +""" +Check CPU features in the host vs the guest. + +This test can highlight differences between the host and what the guest sees. + +No CPU templates as we are interested only on what is passed through to the guest by default. +For that, check test_feat_parity.py +""" + +import os + +from framework import utils +from framework.properties import global_props +from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel + +CPU_MODEL = global_props.cpu_codename + +INTEL_HOST_ONLY_FEATS = { + "acpi", + "aperfmperf", + "arch_perfmon", + "art", + "bts", + "cat_l3", + "cdp_l3", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "dca", + "ds_cpl", + "dtes64", + "dtherm", + "dts", + "epb", + "ept", + "ept_ad", + "est", + "flexpriority", + "flush_l1d", + "hwp", + "hwp_act_window", + "hwp_epp", + "hwp_pkg_req", + "ida", + "intel_ppin", + "intel_pt", + "mba", + "monitor", + "pbe", + "pdcm", + "pebs", + "pln", + "pts", + "rdt_a", + "sdbg", + "smx", + "tm", + "tm2", + "tpr_shadow", + "vmx", + "vnmi", + "vpid", + "xtpr", +} + + +def test_host_vs_guest_cpu_features(uvm_nano): + """Check CPU features host vs guest""" + + vm = uvm_nano + vm.add_net_iface() + vm.start() + host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) + guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) + + match CPU_MODEL: + case CpuModel.AMD_MILAN: + host_guest_diff_5_10 = { + "amd_ppin", + "aperfmperf", + "bpext", + "cat_l3", + "cdp_l3", + "cpb", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "decodeassists", + "extapic", + "extd_apicid", + "flushbyasid", + "hw_pstate", + "ibs", + "irperf", + "lbrv", + "mba", + "monitor", + "mwaitx", + "overflow_recov", + "pausefilter", + "perfctr_llc", + "perfctr_nb", + "pfthreshold", + "rdpru", + "rdt_a", + "sev", + "sev_es", + "skinit", + "smca", + "sme", + "succor", + "svm_lock", + "tce", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + "wdt", + } + + host_guest_diff_6_1 = host_guest_diff_5_10 - { + "lbrv", + "pausefilter", + "pfthreshold", + "sme", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + } | {"brs", "rapl", "v_spec_ctrl"} + + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == host_guest_diff_5_10 + else: + assert host_feats - guest_feats == host_guest_diff_6_1 + + assert guest_feats - host_feats == { + "hypervisor", + "tsc_adjust", + "tsc_deadline_timer", + "tsc_known_freq", + } + + case CpuModel.INTEL_SKYLAKE: + assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS + assert guest_feats - host_feats == { + "hypervisor", + "tsc_known_freq", + "umip", + } + + case CpuModel.INTEL_CASCADELAKE: + expected_host_minus_guest = INTEL_HOST_ONLY_FEATS + expected_guest_minus_host = { + "hypervisor", + "tsc_known_freq", + "umip", + } + + # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. + # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e + # + # Our test ubuntu host kernel is v6.8 and has the commit. + if global_props.host_linux_version_tpl >= (6, 4): + expected_host_minus_guest -= {"flush_l1d"} + + # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit. + # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d + # + # Our test ubuntu host kernel is v6.8 and has the commit. + host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6) + guest_has_invpcid_single = vm.guest_kernel_version < (6, 6) + if host_has_invpcid_single and not guest_has_invpcid_single: + expected_host_minus_guest |= {"invpcid_single"} + if not host_has_invpcid_single and guest_has_invpcid_single: + expected_guest_minus_host |= {"invpcid_single"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case CpuModel.INTEL_ICELAKE: + host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { + "pconfig", + "tme", + "split_lock_detect", + } + host_guest_diff_6_1 = host_guest_diff_5_10 - { + "bts", + "dtes64", + "dts", + "pebs", + } + + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == host_guest_diff_5_10 + else: + assert host_feats - guest_feats == host_guest_diff_6_1 + + assert guest_feats - host_feats == { + "hypervisor", + "tsc_known_freq", + } + + case CpuModel.ARM_NEOVERSE_N1: + expected_guest_minus_host = set() + expected_host_minus_guest = set() + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case CpuModel.ARM_NEOVERSE_V1: + expected_guest_minus_host = set() + # KVM does not enable PAC or SVE features by default + # and Firecracker does not enable them either. + expected_host_minus_guest = {"paca", "pacg", "sve", "svebf16", "svei8mm"} + + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since + # they have an errata whereby an MSR to the SSBS special-purpose register does not + # affect subsequent speculative instructions, permitting speculative store bypassing for + # a window of time. + # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641 + # + # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test + # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it. + host_has_ssbs = global_props.host_os not in { + "amzn2", + "amzn2023", + } and global_props.host_linux_version_tpl < (6, 11) + guest_has_ssbs = vm.guest_kernel_version < (6, 11) + + if host_has_ssbs and not guest_has_ssbs: + expected_host_minus_guest |= {"ssbs"} + if not host_has_ssbs and guest_has_ssbs: + expected_guest_minus_host |= {"ssbs"} + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + + case _: + # only fail if running in CI + if os.environ.get("BUILDKITE") is not None: + assert ( + guest_feats == host_feats + ), f"Cpu model {CPU_MODEL} is not supported" 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 f8bbe1ef52e..a966e253c46 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -22,7 +22,6 @@ from framework.defs import SUPPORTED_HOST_KERNELS from framework.properties import global_props from framework.utils_cpu_templates import SUPPORTED_CPU_TEMPLATES -from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel PLATFORM = platform.machine() UNSUPPORTED_HOST_KERNEL = ( @@ -203,203 +202,6 @@ def test_brand_string(uvm_plain_any): assert False -INTEL_HOST_ONLY_FEATS = { - "acpi", - "aperfmperf", - "arch_perfmon", - "art", - "bts", - "cat_l3", - "cdp_l3", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "dca", - "ds_cpl", - "dtes64", - "dtherm", - "dts", - "epb", - "ept", - "ept_ad", - "est", - "flexpriority", - "flush_l1d", - "hwp", - "hwp_act_window", - "hwp_epp", - "hwp_pkg_req", - "ida", - "intel_ppin", - "intel_pt", - "mba", - "monitor", - "pbe", - "pdcm", - "pebs", - "pln", - "pts", - "rdt_a", - "sdbg", - "smx", - "tm", - "tm2", - "tpr_shadow", - "vmx", - "vnmi", - "vpid", - "xtpr", -} - - -def test_host_vs_guest_cpu_features_x86_64(uvm_nano): - """Check CPU features host vs guest""" - - vm = uvm_nano - vm.add_net_iface() - vm.start() - host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" ")) - - cpu_model = cpuid_utils.get_cpu_codename() - match cpu_model: - case CpuModel.AMD_MILAN: - host_guest_diff_5_10 = { - "amd_ppin", - "aperfmperf", - "bpext", - "cat_l3", - "cdp_l3", - "cpb", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "decodeassists", - "extapic", - "extd_apicid", - "flushbyasid", - "hw_pstate", - "ibs", - "irperf", - "lbrv", - "mba", - "monitor", - "mwaitx", - "overflow_recov", - "pausefilter", - "perfctr_llc", - "perfctr_nb", - "pfthreshold", - "rdpru", - "rdt_a", - "sev", - "sev_es", - "skinit", - "smca", - "sme", - "succor", - "svm_lock", - "tce", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - "wdt", - } - - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "lbrv", - "pausefilter", - "pfthreshold", - "sme", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - } | {"brs", "rapl", "v_spec_ctrl"} - - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 - else: - assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_adjust", - "tsc_deadline_timer", - "tsc_known_freq", - } - case CpuModel.INTEL_SKYLAKE: - assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - "umip", - } - case CpuModel.INTEL_CASCADELAKE: - expected_host_minus_guest = INTEL_HOST_ONLY_FEATS - expected_guest_minus_host = { - "hypervisor", - "tsc_known_freq", - "umip", - } - - # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. - # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e - # - # Our test ubuntu host kernel is v6.8 and has the commit. - if global_props.host_linux_version_tpl >= (6, 4): - expected_host_minus_guest -= {"flush_l1d"} - - # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit. - # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d - # - # Our test ubuntu host kernel is v6.8 and has the commit. - host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6) - guest_has_invpcid_single = vm.guest_kernel_version < (6, 6) - if host_has_invpcid_single and not guest_has_invpcid_single: - expected_host_minus_guest |= {"invpcid_single"} - if not host_has_invpcid_single and guest_has_invpcid_single: - expected_guest_minus_host |= {"invpcid_single"} - - assert host_feats - guest_feats == expected_host_minus_guest - assert guest_feats - host_feats == expected_guest_minus_host - case CpuModel.INTEL_ICELAKE: - host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | { - "pconfig", - "tme", - "split_lock_detect", - } - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "bts", - "dtes64", - "dts", - "pebs", - } - - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 - else: - assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - } - case CpuModel.AMD_GENOA: - # Return here to allow the test to pass until CPU features to enable are confirmed - return - case _: - if os.environ.get("BUILDKITE") is not None: - assert ( - guest_feats == host_feats - ), f"Cpu model {cpu_model} is not supported" - - # From the `Intel® 64 Architecture x2APIC Specification` # (https://courses.cs.washington.edu/courses/cse451/24wi/documentation/x2apic.pdf): # > The X2APIC MSRs cannot to be loaded and stored on VMX transitions. A VMX transition fails From 41f435929c647bb3dc7ad9acebccee3fde9c54a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 11:59:20 +0100 Subject: [PATCH 067/464] tests: add helper method MicrovmFactory.build_from_snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fairly common repeated pattern, so extract it into a method to make writing tests simpler. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 4 +- tests/framework/microvm.py | 7 +++ .../integration_tests/functional/test_api.py | 5 +- .../functional/test_balloon.py | 4 +- .../functional/test_cmd_line_parameters.py | 4 +- .../functional/test_snapshot_basic.py | 52 ++++++------------- .../functional/test_snapshot_editor.py | 4 +- .../test_snapshot_not_losing_dirty_pages.py | 7 +-- .../functional/test_vsock.py | 9 +--- 9 files changed, 31 insertions(+), 65 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a2990a56c98..7cacedb9918 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -477,9 +477,7 @@ def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) snapshot = uvm.snapshot_full() uvm.kill() - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot, resume=True) + uvm2 = microvm_factory.build_from_snapshot(snapshot) uvm2.cpu_template_name = uvm.cpu_template_name return uvm2 diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 832f56a877e..572437c758b 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -1084,6 +1084,13 @@ def build(self, kernel=None, rootfs=None, **kwargs): vm.ssh_key = ssh_key return vm + def build_from_snapshot(self, snapshot: Snapshot): + """Build a microvm from a snapshot""" + vm = self.build() + vm.spawn() + vm.restore_from_snapshot(snapshot, resume=True) + return vm + def kill(self): """Clean up all built VMs""" for vm in self.vms: diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 27366529c39..1e54c7b4fb1 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -1166,10 +1166,7 @@ def test_get_full_config_after_restoring_snapshot(microvm_factory, uvm_nano): ] snapshot = uvm_nano.snapshot_full() - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot, resume=True) - + uvm2 = microvm_factory.build_from_snapshot(snapshot) expected_cfg = setup_cfg.copy() # We expect boot-source to be set with the following values diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index ee750dcac7d..2c59fd2e814 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -484,9 +484,7 @@ def test_balloon_snapshot(microvm_factory, guest_kernel, rootfs): assert first_reading > second_reading snapshot = vm.snapshot_full() - microvm = microvm_factory.build() - microvm.spawn() - microvm.restore_from_snapshot(snapshot, resume=True) + microvm = microvm_factory.build_from_snapshot(snapshot) # Get the firecracker from snapshot pid, and open an ssh connection. firecracker_pid = microvm.firecracker_pid diff --git a/tests/integration_tests/functional/test_cmd_line_parameters.py b/tests/integration_tests/functional/test_cmd_line_parameters.py index 25e47a50e17..79af938b1f7 100644 --- a/tests/integration_tests/functional/test_cmd_line_parameters.py +++ b/tests/integration_tests/functional/test_cmd_line_parameters.py @@ -96,9 +96,7 @@ def test_cli_metrics_if_resume_no_metrics(uvm_plain, microvm_factory): snapshot = uvm1.snapshot_full() # When: restoring from the snapshot - uvm2 = microvm_factory.build() - uvm2.spawn() - uvm2.restore_from_snapshot(snapshot) + uvm2 = microvm_factory.build_from_snapshot(snapshot) # Then: the old metrics configuration does not exist metrics2 = Path(uvm2.jailer.chroot_path()) / metrics_path.name diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index ac596440f67..4030bb4e981 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -50,39 +50,25 @@ def _get_guest_drive_size(ssh_connection, guest_dev_name="/dev/vdb"): return lines[1].strip() -def test_resume_after_restoration(uvm_nano, microvm_factory): - """Tests snapshot is resumable after restoration. +@pytest.mark.parametrize("resume_at_restore", [True, False]) +def test_resume(uvm_nano, microvm_factory, resume_at_restore): + """Tests snapshot is resumable at or after restoration. - Check that a restored microVM is resumable by calling PATCH /vm with Resumed - after PUT /snapshot/load with `resume_vm=False`. + Check that a restored microVM is resumable by either + a. PUT /snapshot/load with `resume_vm=False`, then calling PATCH /vm resume=True + b. PUT /snapshot/load with `resume_vm=True` """ vm = uvm_nano vm.add_net_iface() vm.start() - - snapshot = vm.snapshot_full() - - restored_vm = microvm_factory.build() - restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot) - restored_vm.resume() - - -def test_resume_at_restoration(uvm_nano, microvm_factory): - """Tests snapshot is resumable at restoration. - - Check that a restored microVM is resumable by calling PUT /snapshot/load - with `resume_vm=True`. - """ - vm = uvm_nano - vm.add_net_iface() - vm.start() - snapshot = vm.snapshot_full() - restored_vm = microvm_factory.build() restored_vm.spawn() - restored_vm.restore_from_snapshot(snapshot, resume=True) + restored_vm.restore_from_snapshot(snapshot, resume=resume_at_restore) + if not resume_at_restore: + assert restored_vm.state == "Paused" + restored_vm.resume() + assert restored_vm.state == "Running" def test_snapshot_current_version(uvm_nano): @@ -228,9 +214,7 @@ def test_patch_drive_snapshot(uvm_nano, microvm_factory): # Load snapshot in a new Firecracker microVM. logger.info("Load snapshot, mem %s", snapshot.mem) - vm = microvm_factory.build() - vm.spawn() - vm.restore_from_snapshot(snapshot, resume=True) + vm = microvm_factory.build_from_snapshot(snapshot) # Attempt to connect to resumed microvm and verify the new microVM has the # right scratch drive. @@ -319,9 +303,7 @@ def test_negative_postload_api(uvm_plain, microvm_factory): basevm.kill() # Do not resume, just load, so we can still call APIs that work. - microvm = microvm_factory.build() - microvm.spawn() - microvm.restore_from_snapshot(snapshot, resume=True) + microvm = microvm_factory.build_from_snapshot(snapshot) fail_msg = "The requested operation is not supported after starting the microVM" with pytest.raises(RuntimeError, match=fail_msg): @@ -486,9 +468,7 @@ def test_diff_snapshot_overlay(guest_kernel, rootfs, microvm_factory): assert not filecmp.cmp(merged_snapshot.mem, first_snapshot_backup, shallow=False) - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(merged_snapshot, resume=True) + _ = microvm_factory.build_from_snapshot(merged_snapshot) # Check that the restored VM works @@ -510,9 +490,7 @@ def test_snapshot_overwrite_self(guest_kernel, rootfs, microvm_factory): snapshot = base_vm.snapshot_full() base_vm.kill() - vm = microvm_factory.build() - vm.spawn() - vm.restore_from_snapshot(snapshot, resume=True) + vm = microvm_factory.build_from_snapshot(snapshot) # When restoring a snapshot, vm.restore_from_snapshot first copies # the memory file (inside of the jailer) to /mem.src diff --git a/tests/integration_tests/functional/test_snapshot_editor.py b/tests/integration_tests/functional/test_snapshot_editor.py index 4d466a441ce..9323695628c 100644 --- a/tests/integration_tests/functional/test_snapshot_editor.py +++ b/tests/integration_tests/functional/test_snapshot_editor.py @@ -68,6 +68,4 @@ def test_remove_regs(uvm_nano, microvm_factory): assert MIDR_EL1 not in stdout # test that we can restore from a snapshot - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) + _ = microvm_factory.build_from_snapshot(snapshot) diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py index 5584cfceac8..79366f13f0b 100644 --- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py +++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py @@ -63,9 +63,6 @@ def test_diff_snapshot_works_after_error( # Now there is enough space for it to work snap2 = uvm.snapshot_diff() - - vm2 = microvm_factory.build() - vm2.spawn() - vm2.restore_from_snapshot(snap2, resume=True) - uvm.kill() + + _vm2 = microvm_factory.build_from_snapshot(snap2) diff --git a/tests/integration_tests/functional/test_vsock.py b/tests/integration_tests/functional/test_vsock.py index 2d540b8f934..dfa02510b37 100644 --- a/tests/integration_tests/functional/test_vsock.py +++ b/tests/integration_tests/functional/test_vsock.py @@ -199,10 +199,7 @@ def test_vsock_transport_reset_h2g( test_vm.kill() # Load snapshot. - - vm2 = microvm_factory.build() - vm2.spawn() - vm2.restore_from_snapshot(snapshot, resume=True) + vm2 = microvm_factory.build_from_snapshot(snapshot) # Check that vsock device still works. # Test guest-initiated connections. @@ -231,9 +228,7 @@ def test_vsock_transport_reset_g2h(uvm_nano, microvm_factory): for _ in range(5): # Load snapshot. - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) + new_vm = microvm_factory.build_from_snapshot(snapshot) # After snap restore all vsock connections should be # dropped. This means guest socat should exit same way From 54ae107941077f2444617d84fa8b8d6f973eb146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 12:03:31 +0100 Subject: [PATCH 068/464] tests: refactor test_rng with uvm_any MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite test_rng using uvm_any. Signed-off-by: Pablo Barbáchano --- .../integration_tests/functional/test_rng.py | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/tests/integration_tests/functional/test_rng.py b/tests/integration_tests/functional/test_rng.py index b40aa66033d..1893230c51a 100644 --- a/tests/integration_tests/functional/test_rng.py +++ b/tests/integration_tests/functional/test_rng.py @@ -8,11 +8,9 @@ from host_tools.network import SSHConnection -@pytest.fixture(params=[None]) -def uvm_with_rng(uvm_plain, request): - """Fixture of a microvm with virtio-rng configured""" - rate_limiter = request.param - uvm = uvm_plain +def uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter): + """Return a booted microvm with virtio-rng configured""" + uvm = microvm_factory.build(guest_kernel, rootfs) uvm.spawn(log_level="INFO") uvm.basic_config(vcpu_count=2, mem_size_mib=256) uvm.add_net_iface() @@ -23,6 +21,34 @@ def uvm_with_rng(uvm_plain, request): return uvm +def uvm_with_rng_restored(microvm_factory, guest_kernel, rootfs, rate_limiter): + """Return a restored uvm with virtio-rng configured""" + uvm = uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter) + snapshot = uvm.snapshot_full() + uvm.kill() + uvm2 = microvm_factory.build_from_snapshot(snapshot) + uvm2.rng_rate_limiter = uvm.rng_rate_limiter + return uvm2 + + +@pytest.fixture(params=[uvm_with_rng_booted, uvm_with_rng_restored]) +def uvm_ctor(request): + """Fixture to return uvms with different constructors""" + return request.param + + +@pytest.fixture(params=[None]) +def rate_limiter(request): + """Fixture to return different rate limiters""" + return request.param + + +@pytest.fixture +def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, rate_limiter): + """Return booted and restored uvms""" + return uvm_ctor(microvm_factory, guest_kernel, rootfs, rate_limiter) + + def list_rng_available(ssh_connection: SSHConnection) -> list[str]: """Returns a list of rng devices available in the VM""" return ( @@ -62,35 +88,17 @@ def test_rng_not_present(uvm_nano): ), "virtio_rng device should not be available in the uvm" -def test_rng_present(uvm_with_rng): +def test_rng_present(uvm_any): """ Test a guest microVM with an entropy defined configured and ensure that we can access `/dev/hwrng` """ - vm = uvm_with_rng + vm = uvm_any assert_virtio_rng_is_current_hwrng_device(vm.ssh) check_entropy(vm.ssh) -def test_rng_snapshot(uvm_with_rng, microvm_factory): - """ - Test that a virtio-rng device is functional after resuming from - a snapshot - """ - - vm = uvm_with_rng - assert_virtio_rng_is_current_hwrng_device(vm.ssh) - check_entropy(vm.ssh) - snapshot = vm.snapshot_full() - - new_vm = microvm_factory.build() - new_vm.spawn() - new_vm.restore_from_snapshot(snapshot, resume=True) - assert_virtio_rng_is_current_hwrng_device(new_vm.ssh) - check_entropy(new_vm.ssh) - - def _get_percentage_difference(measured, base): """Return the percentage delta between the arguments.""" if measured == base: @@ -199,7 +207,7 @@ def _rate_limiter_id(rate_limiter): # parametrize the RNG rate limiter @pytest.mark.parametrize( - "uvm_with_rng", + "rate_limiter", [ {"bandwidth": {"size": 1000, "refill_time": 100}}, {"bandwidth": {"size": 10000, "refill_time": 100}}, @@ -208,16 +216,14 @@ def _rate_limiter_id(rate_limiter): indirect=True, ids=_rate_limiter_id, ) -def test_rng_bw_rate_limiter(uvm_with_rng): +@pytest.mark.parametrize("uvm_ctor", [uvm_with_rng_booted], indirect=True) +def test_rng_bw_rate_limiter(uvm_any): """ Test that rate limiter without initial burst budget works """ - vm = uvm_with_rng - # _start_vm_with_rng(vm, rate_limiter) - + vm = uvm_any size = vm.rng_rate_limiter["bandwidth"]["size"] refill_time = vm.rng_rate_limiter["bandwidth"]["refill_time"] - expected_kbps = size / refill_time assert_virtio_rng_is_current_hwrng_device(vm.ssh) From 80591e0d8af9c6ffcef0744d34246adf00b7c781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Sat, 23 Nov 2024 13:55:58 +0100 Subject: [PATCH 069/464] tests: drop unused static cpu_templates fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixture is not used anymore, as it is mostly superseded by cpu_template_any. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 7 ------- .../functional/test_cpu_features_x86_64.py | 15 +++++++-------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7cacedb9918..b599ffc79ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -292,13 +292,6 @@ def microvm_factory(request, record_property, results_dir): uvm_factory.kill() -@pytest.fixture(params=static_cpu_templates_params()) -def cpu_template(request, record_property): - """Return all static CPU templates supported by the vendor.""" - record_property("static_cpu_template", request.param) - return request.param - - @pytest.fixture(params=custom_cpu_templates_params()) def custom_cpu_template(request, record_property): """Return all dummy custom CPU templates supported by the vendor.""" 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 a966e253c46..1af6a39f83a 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -952,18 +952,16 @@ def check_enabled_features(test_microvm, cpu_template): ) -def test_c3_on_skylake_show_warning(uvm_plain, 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 C3 template. + 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, - cpu_template=cpu_template, - ) + uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.add_net_iface() + uvm.set_cpu_template(cpu_template_any) uvm.start() message = ( @@ -972,7 +970,8 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template): "does not apply the mitigation against MMIO stale data " "vulnerability." ) - if uvm.cpu_template_name == "c3" and global_props.cpu_codename == "INTEL_SKYLAKE": + + 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 From b0cc581bb090a5c41df95c3d2276dc93ca179b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 28 Nov 2024 23:25:56 +0100 Subject: [PATCH 070/464] tests: simplify rootfs fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we only have one rootfs, simplify the fixture to return a single value. This will have also not show it as part of the test instance name. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 23 ++++++++++++----------- tests/framework/artifacts.py | 10 ++-------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index b599ffc79ab..5ed61083014 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,7 +35,7 @@ import host_tools.cargo_build as build_tools from framework import defs, utils -from framework.artifacts import kernel_params, rootfs_params +from framework.artifacts import disks, kernel_params from framework.microvm import MicroVMFactory from framework.properties import global_props from framework.utils_cpu_templates import ( @@ -354,13 +354,6 @@ def guest_kernel_fxt(request, record_property): return kernel -def rootfs_fxt(request, record_property): - """Return all supported rootfs.""" - fs = request.param - record_property("rootfs", fs.name) - return fs - - # Fixtures for all guest kernels, and specific versions guest_kernel = pytest.fixture(guest_kernel_fxt, params=kernel_params("vmlinux-*")) guest_kernel_acpi = pytest.fixture( @@ -380,9 +373,17 @@ def rootfs_fxt(request, record_property): params=kernel_params("vmlinux-6.1*"), ) -# Fixtures for all Ubuntu rootfs, and specific versions -rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs")) -rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4")) + +@pytest.fixture +def rootfs(): + """Return an Ubuntu 24.04 read-only rootfs""" + return disks("ubuntu-24.04.squashfs")[0] + + +@pytest.fixture +def rootfs_rw(): + """Return an Ubuntu 24.04 ext4 rootfs""" + return disks("ubuntu-24.04.ext4")[0] @pytest.fixture diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py index 77584f02129..0ed27c16b61 100644 --- a/tests/framework/artifacts.py +++ b/tests/framework/artifacts.py @@ -44,9 +44,9 @@ def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator: break -def disks(glob) -> Iterator: +def disks(glob) -> list: """Return supported rootfs""" - yield from sorted(ARTIFACT_DIR.glob(glob)) + return sorted(ARTIFACT_DIR.glob(glob)) def kernel_params( @@ -57,12 +57,6 @@ def kernel_params( yield pytest.param(kernel, id=kernel.name) -def rootfs_params(glob="ubuntu-*.squashfs") -> Iterator: - """Return supported rootfs as pytest parameters""" - for rootfs in disks(glob=glob): - yield pytest.param(rootfs, id=rootfs.name) - - @dataclass(frozen=True, repr=True) class FirecrackerArtifact: """Utility class for Firecracker binary artifacts.""" From d7734e2c3faca1a1870588ae01b8667f5cef254c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 29 Nov 2024 09:32:07 +0100 Subject: [PATCH 071/464] tests: parametrize uvm_any fixture family with vcpus and memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a parameter so that we can control vcpu number and memory. Right now it uses a hardcoded value, but it can be overridden per test. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 54 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5ed61083014..ac73b4bd8ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -455,20 +455,34 @@ def uvm_with_initrd( yield uvm -def uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template): +@pytest.fixture +def vcpu_count(): + """Return default vcpu_count. Use indirect parametrization to override.""" + return 2 + + +@pytest.fixture +def mem_size_mib(): + """Return memory size. Use indirect parametrization to override.""" + return 256 + + +def uvm_booted( + microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256 +): """Return a booted uvm""" uvm = microvm_factory.build(guest_kernel, rootfs) uvm.spawn() - uvm.basic_config(vcpu_count=2, mem_size_mib=256) + uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib) uvm.set_cpu_template(cpu_template) uvm.add_net_iface() uvm.start() return uvm -def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template): +def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs): """Return a restored uvm""" - uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template) + uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs) snapshot = uvm.snapshot_full() uvm.kill() uvm2 = microvm_factory.build_from_snapshot(snapshot) @@ -483,12 +497,36 @@ def uvm_ctor(request): @pytest.fixture -def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, cpu_template_any): +def uvm_any( + microvm_factory, + uvm_ctor, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count, + mem_size_mib, +): """Return booted and restored uvms""" - return uvm_ctor(microvm_factory, guest_kernel, rootfs, cpu_template_any) + return uvm_ctor( + microvm_factory, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count=vcpu_count, + mem_size_mib=mem_size_mib, + ) @pytest.fixture -def uvm_any_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any): +def uvm_any_booted( + microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib +): """Return booted uvms""" - return uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template_any) + return uvm_booted( + microvm_factory, + guest_kernel, + rootfs, + cpu_template_any, + vcpu_count=vcpu_count, + mem_size_mib=mem_size_mib, + ) From 1f94a59b1b04626e14a02dbd4bcbbdf3b79fefd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Dec 2024 11:24:30 +0100 Subject: [PATCH 072/464] fix(tests): save snapshot metadata when saving to disk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We missed saving metadata when saving to disk Fixes: 426790e4001ac7315554f876637298fb37fb85a8 Signed-off-by: Pablo Barbáchano --- tests/framework/microvm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 572437c758b..91b88cc4c28 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -150,6 +150,7 @@ def save_to(self, dst: Path): "disks": new_disks, "ssh_key": self.ssh_key.name, "snapshot_type": self.snapshot_type.value, + "meta": self.meta, } snap_json = dst / "snapshot.json" snap_json.write_text(json.dumps(obj)) @@ -937,7 +938,7 @@ def make_snapshot( ssh_key=self.ssh_key, snapshot_type=snapshot_type, meta={ - "kernel_file": self.kernel_file, + "kernel_file": str(self.kernel_file), }, ) @@ -978,6 +979,8 @@ def restore_from_snapshot( for key, value in snapshot.meta.items(): setattr(self, key, value) + # Adjust things just in case + self.kernel_file = Path(self.kernel_file) self.api.snapshot_load.put( mem_backend=mem_backend, From 761909de71d2e4a8c110334cde928fab34831f61 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 6 Dec 2024 13:53:02 +0000 Subject: [PATCH 073/464] fix(tests): add switch case for AMD_GENOA to the cpu features test During previous refactoring, this switch was accidentally removed. Signed-off-by: Egor Lazarchuk --- .../functional/test_cpu_features_host_vs_guest.py | 4 ++++ 1 file changed, 4 insertions(+) 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 bbf4ed57d21..71e61262c69 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 @@ -150,6 +150,10 @@ def test_host_vs_guest_cpu_features(uvm_nano): "tsc_known_freq", } + case CpuModel.AMD_GENOA: + # Return here to allow the test to pass until CPU features to enable are confirmed + return + case CpuModel.INTEL_SKYLAKE: assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS assert guest_feats - host_feats == { From f59717cfd19ae0634962b70fed14bf71c6b269aa Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Tue, 3 Dec 2024 07:25:11 +0000 Subject: [PATCH 074/464] doc: Use a valid bitmap for vcpu_features As seen in #4925, setting the least significant bits of vcpu_features field to 0 make secondary CPUs not work. There is no reason to use such an invalid example in doc. The sample in doc intended to enable PAC (Pointer Authentication) since it checks capabilities 171 and 172 [2]. Thus, not set the other bits than bits 5 and 6. [1]: https://elixir.bootlin.com/linux/v6.12.1/source/include/uapi/linux/kvm.h#L868-L869 [2]: https://elixir.bootlin.com/linux/v6.12.1/source/arch/arm64/include/uapi/asm/kvm.h#L108-L109 Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpu-templates.md | 2 +- docs/cpu_templates/schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cpu_templates/cpu-templates.md b/docs/cpu_templates/cpu-templates.md index e00e71f26e2..a2d8b06fceb 100644 --- a/docs/cpu_templates/cpu-templates.md +++ b/docs/cpu_templates/cpu-templates.md @@ -180,7 +180,7 @@ curl --unix-socket /tmp/firecracker.socket -i \ -H 'Content-Type: application/json' \ -d '{ "kvm_capabilities": ["171", "172"], - "vcpu_features": [{ "index": 0, "bitmap": "0b1100000" }] + "vcpu_features": [{ "index": 0, "bitmap": "0b11xxxxx" }] "reg_modifiers": [ { "addr": "0x603000000013c020", diff --git a/docs/cpu_templates/schema.json b/docs/cpu_templates/schema.json index 76a11697e06..27844756941 100644 --- a/docs/cpu_templates/schema.json +++ b/docs/cpu_templates/schema.json @@ -26,7 +26,7 @@ "bitmap": { "description": "Bitmap for modifying the 32 bit field in kvm_vcpu_init::features. Must be in the format `0b[01x]{1,32}`. Corresponding bits will be cleared (`0`), set (`1`) or left intact (`x`). (`_`) can be used as a separator.", "type": "string", - "examples": ["0b1100000"] + "examples": ["0b11xxxxx"] } } } From da1c3b37f3170af1e03d69daa8ce106d56b8511b Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 4 Dec 2024 07:49:40 +0000 Subject: [PATCH 075/464] test: Check all vCPUs are online As seen in #4925, a bad CPU template made secondary CPUs not come up. To catch similar bugs of CPU templates, check all the vCPUs are online from guests' perspective. Signed-off-by: Takahiro Itazuri --- tests/framework/microvm.py | 1 + .../functional/test_cpu_multiple.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/integration_tests/functional/test_cpu_multiple.py diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 91b88cc4c28..eb755ffc5fa 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -939,6 +939,7 @@ def make_snapshot( snapshot_type=snapshot_type, meta={ "kernel_file": str(self.kernel_file), + "vcpus_count": self.vcpus_count, }, ) diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_multiple.py new file mode 100644 index 00000000000..8d150950a38 --- /dev/null +++ b/tests/integration_tests/functional/test_cpu_multiple.py @@ -0,0 +1,18 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Test all vCPUs are configured correctly and work properly. + +This test suite aims to catch bugs of Firecracker's vCPU configuration and +CPU templates especially under multi-vCPU setup, by checking that all vCPUs +are operating identically, except for the expected differences. +""" + + +def test_all_vcpus_online(uvm_any): + """Check all vCPUs are online inside guest""" + assert ( + uvm_any.ssh.check_output("cat /sys/devices/system/cpu/online").stdout.strip() + == f"0-{uvm_any.vcpus_count - 1}" + ) From 21472d0e4ab5e2ac6b57710eaeaade02c1d85270 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 4 Dec 2024 08:37:54 +0000 Subject: [PATCH 076/464] test: Check all vCPUs have the same features inside guest The test ensures Firecracker or CPU templates don't configure CPU features differently between vCPUs. Note that whether the printed CPU features are expected or not should be tested in (arch-specific) test_cpu_features_*.py only for vCPU 0. Thus, we only test the equivalence of all CPUs in the same guest. Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_multiple.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_multiple.py index 8d150950a38..1dd38a10906 100644 --- a/tests/integration_tests/functional/test_cpu_multiple.py +++ b/tests/integration_tests/functional/test_cpu_multiple.py @@ -16,3 +16,21 @@ def test_all_vcpus_online(uvm_any): uvm_any.ssh.check_output("cat /sys/devices/system/cpu/online").stdout.strip() == f"0-{uvm_any.vcpus_count - 1}" ) + + +def test_all_vcpus_have_same_features(uvm_any): + """ + Check all vCPUs have the same features inside guest. + + This test ensures Firecracker or CPU templates don't configure CPU features + differently between vCPUs. + + Note that whether the shown CPU features are expected or not should be + tested in (arch-specific) test_cpu_features_*.py only for vCPU 0. Thus, we + only test the equivalence of all CPUs in the same guest. + """ + # Get a feature set for each CPU and deduplicate them. + unique_feature_lists = uvm_any.ssh.check_output( + 'grep -E "^(flags|Features)" /proc/cpuinfo | uniq' + ).stdout.splitlines() + assert len(unique_feature_lists) == 1 From db2e270d996b3e31037bcf5bd7e1292103f2f39a Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 6 Dec 2024 07:45:57 +0000 Subject: [PATCH 077/464] test: Remove test_max_cpus.py test_max_cpus.py tests vCPUs are online only on a microVM without CPU templates, which is now covered as part of test_all_vcpus_online(). Remove the test and use the maximum number of vCPUs in the new tests. Signed-off-by: Takahiro Itazuri --- .../{test_cpu_multiple.py => test_cpu_all.py} | 7 ++++++ .../functional/test_max_vcpus.py | 23 ------------------- 2 files changed, 7 insertions(+), 23 deletions(-) rename tests/integration_tests/functional/{test_cpu_multiple.py => test_cpu_all.py} (87%) delete mode 100644 tests/integration_tests/functional/test_max_vcpus.py diff --git a/tests/integration_tests/functional/test_cpu_multiple.py b/tests/integration_tests/functional/test_cpu_all.py similarity index 87% rename from tests/integration_tests/functional/test_cpu_multiple.py rename to tests/integration_tests/functional/test_cpu_all.py index 1dd38a10906..6b934ffa394 100644 --- a/tests/integration_tests/functional/test_cpu_multiple.py +++ b/tests/integration_tests/functional/test_cpu_all.py @@ -9,7 +9,13 @@ are operating identically, except for the expected differences. """ +import pytest +# Use the maximum number of vCPUs supported by Firecracker +MAX_VCPUS = 32 + + +@pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) def test_all_vcpus_online(uvm_any): """Check all vCPUs are online inside guest""" assert ( @@ -18,6 +24,7 @@ def test_all_vcpus_online(uvm_any): ) +@pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) def test_all_vcpus_have_same_features(uvm_any): """ Check all vCPUs have the same features inside guest. diff --git a/tests/integration_tests/functional/test_max_vcpus.py b/tests/integration_tests/functional/test_max_vcpus.py deleted file mode 100644 index 05c1f3c51ff..00000000000 --- a/tests/integration_tests/functional/test_max_vcpus.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Tests scenario for microvms with max vcpus(32).""" - -MAX_VCPUS = 32 - - -def test_max_vcpus(uvm_plain): - """ - Test if all configured guest vcpus are online. - """ - microvm = uvm_plain - microvm.spawn() - - # Configure a microVM with 32 vCPUs. - microvm.basic_config(vcpu_count=MAX_VCPUS) - microvm.add_net_iface() - microvm.start() - - cmd = "nproc" - _, stdout, stderr = microvm.ssh.run(cmd) - assert stderr == "" - assert int(stdout) == MAX_VCPUS From 3b5f161ae236a7a4c5887959de0a011d245bca6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 6 Dec 2024 11:48:41 +0100 Subject: [PATCH 078/464] tests: flesh out the AMD Genoa host vs guest test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record the differences wrt AMD Milan CPUs. Signed-off-by: Pablo Barbáchano --- .../test_cpu_features_host_vs_guest.py | 179 ++++++++++-------- 1 file changed, 98 insertions(+), 81 deletions(-) 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 71e61262c69..d2fd4936328 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 @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # pylint: disable=too-many-statements +# pylint: disable=too-many-branches """ Check CPU features in the host vs the guest. @@ -70,6 +71,91 @@ "xtpr", } +INTEL_GUEST_ONLY_FEATS = { + "hypervisor", + "tsc_known_freq", + "umip", +} + +AMD_MILAN_HOST_ONLY_FEATS = { + "amd_ppin", + "aperfmperf", + "bpext", + "cat_l3", + "cdp_l3", + "cpb", + "cqm", + "cqm_llc", + "cqm_mbm_local", + "cqm_mbm_total", + "cqm_occup_llc", + "decodeassists", + "extapic", + "extd_apicid", + "flushbyasid", + "hw_pstate", + "ibs", + "irperf", + "lbrv", + "mba", + "monitor", + "mwaitx", + "overflow_recov", + "pausefilter", + "perfctr_llc", + "perfctr_nb", + "pfthreshold", + "rdpru", + "rdt_a", + "sev", + "sev_es", + "skinit", + "smca", + "sme", + "succor", + "svm_lock", + "tce", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", + "wdt", +} + +AMD_GUEST_ONLY_FEATS = { + "hypervisor", + "tsc_adjust", + "tsc_deadline_timer", + "tsc_known_freq", +} + +AMD_MILAN_HOST_ONLY_FEATS_6_1 = AMD_MILAN_HOST_ONLY_FEATS - { + "lbrv", + "pausefilter", + "pfthreshold", + "sme", + "tsc_scale", + "v_vmsave_vmload", + "vgif", + "vmcb_clean", +} | {"brs", "rapl", "v_spec_ctrl"} + +AMD_GENOA_HOST_ONLY_FEATS = AMD_MILAN_HOST_ONLY_FEATS | { + "avic", + "flush_l1d", + "ibrs_enhanced", +} + +AMD_GENOA_HOST_ONLY_FEATS_6_1 = AMD_MILAN_HOST_ONLY_FEATS_6_1 - {"brs"} | { + "avic", + "amd_lbr_v2", + "cppc", + "flush_l1d", + "ibrs_enhanced", + "perfmon_v2", + "x2avic", +} + def test_host_vs_guest_cpu_features(uvm_nano): """Check CPU features host vs guest""" @@ -82,93 +168,28 @@ def test_host_vs_guest_cpu_features(uvm_nano): match CPU_MODEL: case CpuModel.AMD_MILAN: - host_guest_diff_5_10 = { - "amd_ppin", - "aperfmperf", - "bpext", - "cat_l3", - "cdp_l3", - "cpb", - "cqm", - "cqm_llc", - "cqm_mbm_local", - "cqm_mbm_total", - "cqm_occup_llc", - "decodeassists", - "extapic", - "extd_apicid", - "flushbyasid", - "hw_pstate", - "ibs", - "irperf", - "lbrv", - "mba", - "monitor", - "mwaitx", - "overflow_recov", - "pausefilter", - "perfctr_llc", - "perfctr_nb", - "pfthreshold", - "rdpru", - "rdt_a", - "sev", - "sev_es", - "skinit", - "smca", - "sme", - "succor", - "svm_lock", - "tce", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - "wdt", - } - - host_guest_diff_6_1 = host_guest_diff_5_10 - { - "lbrv", - "pausefilter", - "pfthreshold", - "sme", - "tsc_scale", - "v_vmsave_vmload", - "vgif", - "vmcb_clean", - } | {"brs", "rapl", "v_spec_ctrl"} - if global_props.host_linux_version_tpl < (6, 1): - assert host_feats - guest_feats == host_guest_diff_5_10 + assert host_feats - guest_feats == AMD_MILAN_HOST_ONLY_FEATS else: - assert host_feats - guest_feats == host_guest_diff_6_1 + assert host_feats - guest_feats == AMD_MILAN_HOST_ONLY_FEATS_6_1 - assert guest_feats - host_feats == { - "hypervisor", - "tsc_adjust", - "tsc_deadline_timer", - "tsc_known_freq", - } + assert guest_feats - host_feats == AMD_GUEST_ONLY_FEATS case CpuModel.AMD_GENOA: - # Return here to allow the test to pass until CPU features to enable are confirmed - return + if global_props.host_linux_version_tpl < (6, 1): + assert host_feats - guest_feats == AMD_GENOA_HOST_ONLY_FEATS + else: + assert host_feats - guest_feats == AMD_GENOA_HOST_ONLY_FEATS_6_1 + + 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 == { - "hypervisor", - "tsc_known_freq", - "umip", - } + 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 = { - "hypervisor", - "tsc_known_freq", - "umip", - } + expected_guest_minus_host = INTEL_GUEST_ONLY_FEATS # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests. # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e @@ -208,11 +229,7 @@ def test_host_vs_guest_cpu_features(uvm_nano): assert host_feats - guest_feats == host_guest_diff_5_10 else: assert host_feats - guest_feats == host_guest_diff_6_1 - - assert guest_feats - host_feats == { - "hypervisor", - "tsc_known_freq", - } + assert guest_feats - host_feats == INTEL_GUEST_ONLY_FEATS - {"umip"} case CpuModel.ARM_NEOVERSE_N1: expected_guest_minus_host = set() From 83c57e92408537d48b988624222d264b3678f911 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:29:59 +0000 Subject: [PATCH 079/464] build(deps): Bump the firecracker group across 1 directory with 10 updates Bumps the firecracker group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.3` | `2.0.6` | | [zerocopy](https://github.com/google/zerocopy) | `0.8.11` | `0.8.13` | | [clap](https://github.com/clap-rs/clap) | `4.5.21` | `4.5.23` | | [libc](https://github.com/rust-lang/libc) | `0.2.167` | `0.2.168` | | [cargo_toml](https://gitlab.com/lib.rs/cargo_toml) | `0.20.5` | `0.21.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.2` | `1.2.3` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.41` | `0.38.42` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.13` | `1.0.14` | Updates `thiserror` from 2.0.3 to 2.0.6 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.3...2.0.6) Updates `zerocopy` from 0.8.11 to 0.8.13 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.11...v0.8.13) Updates `clap` from 4.5.21 to 4.5.23 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.21...clap_complete-v4.5.23) Updates `libc` from 0.2.167 to 0.2.168 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.168/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.167...0.2.168) Updates `cargo_toml` from 0.20.5 to 0.21.0 - [Commits](https://gitlab.com/lib.rs/cargo_toml/commits/main) Updates `cc` from 1.2.2 to 1.2.3 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.2...cc-v1.2.3) Updates `clap_builder` from 4.5.21 to 4.5.23 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.21...v4.5.23) Updates `clap_lex` from 0.7.3 to 0.7.4 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.3...clap_lex-v0.7.4) Updates `rustix` from 0.38.41 to 0.38.42 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.41...v0.38.42) Updates `unicode-ident` from 1.0.13 to 1.0.14 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.13...1.0.14) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cargo_toml dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_lex dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 76 +++++++++++++++--------------- src/acpi-tables/Cargo.toml | 4 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 6 +-- src/firecracker/Cargo.toml | 8 ++-- src/jailer/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 4 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 6 +-- src/utils/Cargo.toml | 4 +- src/vmm/Cargo.toml | 6 +-- 11 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 521552d3f87..f31b84f68c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,9 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.3", + "thiserror 2.0.6", "vm-memory", - "zerocopy 0.8.11", + "zerocopy 0.8.13", ] [[package]] @@ -244,9 +244,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cargo_toml" -version = "0.20.5" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88da5a13c620b4ca0078845707ea9c3faf11edbc3ffd8497d11d686211cd1ac0" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" dependencies = [ "serde", "toml", @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -359,9 +359,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clippy-tracing" @@ -425,7 +425,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "vmm", "vmm-sys-util", ] @@ -619,7 +619,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "timerfd", "userfaultfd", "utils", @@ -805,7 +805,7 @@ dependencies = [ "log-instrument", "nix 0.29.0", "regex", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -856,9 +856,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" @@ -1138,7 +1138,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -1180,15 +1180,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1216,7 +1216,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm-sys-util", ] @@ -1296,7 +1296,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.3", + "thiserror 2.0.6", "utils", "vmm", "vmm-sys-util", @@ -1336,11 +1336,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.6", ] [[package]] @@ -1356,9 +1356,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", @@ -1432,9 +1432,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-xid" @@ -1499,7 +1499,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "vm-memory", "vmm-sys-util", ] @@ -1613,7 +1613,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.3", + "thiserror 2.0.6", "timerfd", "userfaultfd", "utils", @@ -1623,7 +1623,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.11", + "zerocopy 0.8.13", ] [[package]] @@ -1800,11 +1800,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.11" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce3b5629d87654b53a49002acc2ce64aa5aa7255f5c718374a37ac7fd98c218" +checksum = "67914ab451f3bfd2e69e5e9d2ef3858484e7074d63f204fd166ec391b54de21d" dependencies = [ - "zerocopy-derive 0.8.11", + "zerocopy-derive 0.8.13", ] [[package]] @@ -1820,9 +1820,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.11" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a82c26c3986af2623ec9eb890ff4aa19c006e30a1133dc9bd1830ec1612e20" +checksum = "7988d73a4303ca289df03316bc490e934accf371af6bc745393cf3c2c5c4f25d" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 39b8f1574c9..87b2e7ed626 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,9 +8,9 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.3" +thiserror = "2.0.6" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.11", features = ["derive"] } +zerocopy = { version = "0.8.13", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index e22cd6a1eae..e112095226a 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.21", features = ["derive"] } +clap = { version = "4.5.23", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index eb7c16472e0..0e665f8f521 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,13 +10,13 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.21", features = ["derive", "string"] } +clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 6cd237aaabe..ec20799e798 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,7 +18,7 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -26,15 +26,15 @@ seccompiler = { path = "../seccompiler" } serde = { version = "1.0.215", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] -cargo_toml = "0.20.5" -libc = "0.2.167" +cargo_toml = "0.21.0" +libc = "0.2.168" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index ef9162027be..f486944ac3b 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,11 +12,11 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.3" +thiserror = "2.0.6" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 1615260b03b..8409430340e 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,9 +11,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.3" +thiserror = "2.0.6" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 90477e3e025..93be7082920 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,11 +18,11 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.3" +thiserror = "2.0.6" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 91bbebf7f27..0e42cd11859 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,14 +10,14 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.21", features = ["derive", "string"] } +clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.23" -thiserror = "2.0.3" +thiserror = "2.0.6" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 7f57e5081a0..923155c265e 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -11,10 +11,10 @@ bench = false [dependencies] derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" -libc = "0.2.167" +libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.215", features = ["derive"] } -thiserror = "2.0.3" +thiserror = "2.0.6" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vmm-sys-util = "0.12.1" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 283a47a5982..31acb7362a8 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.0" lazy_static = "1.5.0" -libc = "0.2.167" +libc = "0.2.168" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -37,7 +37,7 @@ semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0.215", features = ["derive", "rc"] } serde_json = "1.0.133" slab = "0.4.7" -thiserror = "2.0.3" +thiserror = "2.0.6" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } @@ -46,7 +46,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.11" } +zerocopy = { version = "0.8.13" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From f90cc5c19e075cb11bda5f8d237bf22636e4ef1d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 16:41:57 +0000 Subject: [PATCH 080/464] chore: update deny.toml the unicode-ident crates changed license from Unicode-DFS-2016 to Unicode-3.0 Signed-off-by: Patrick Roy --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 5cd62715860..be3a1040463 100644 --- a/deny.toml +++ b/deny.toml @@ -5,7 +5,7 @@ allow = [ "Apache-2.0", "BSD-3-Clause", "ISC", - "Unicode-DFS-2016", + "Unicode-3.0", "OpenSSL" ] From 68b7c9923456aa469042b53bc797afaf9d82b765 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 25 Nov 2024 16:54:29 +0000 Subject: [PATCH 081/464] chore(devctr): update rust version to 1.83 Update Rust to 1.83 version Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- rust-toolchain.toml | 2 +- tools/devctr/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ff74857c81d..af10d0da481 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.79.0" +channel = "1.83.0" targets = ["x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl"] profile = "minimal" diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index f0c7c36f759..bebf1309e00 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.79.0" +ARG RUST_TOOLCHAIN="1.83.0" ARG TMP_BUILD_DIR=/tmp/build ARG DEBIAN_FRONTEND=noninteractive ARG PIP_BREAK_SYSTEM_PACKAGES=1 From c5e5794e414a6a377fae64a56ec6f956bcdeda9c Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 28 Nov 2024 21:52:20 +0000 Subject: [PATCH 082/464] chore(clippy): update code with new lints From: Egor Lazarchuk With a new Rust version, new Clippy entered our repository. This commit aligns our codebase with guidance provided by new lints. Also remove a `deny(clippy::pedantic)`, because I'm not fixing those. Signed-off-by: Egor Lazarchuk Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- Cargo.toml | 1 + src/acpi-tables/src/aml.rs | 30 +++++++++---------- src/clippy-tracing/src/main.rs | 2 -- .../src/api_server/request/actions.rs | 3 +- .../src/api_server/request/boot_source.rs | 3 +- .../src/api_server/request/drive.rs | 6 ++-- .../src/api_server/request/logger.rs | 3 +- .../request/machine_configuration.rs | 6 ++-- .../src/api_server/request/metrics.rs | 3 +- .../src/api_server/request/mmds.rs | 9 ++---- src/firecracker/src/api_server/request/net.rs | 6 ++-- .../src/api_server/request/vsock.rs | 3 +- src/seccompiler/src/backend.rs | 2 +- src/seccompiler/src/compiler.rs | 4 +-- src/vmm/benches/queue.rs | 4 +-- src/vmm/src/acpi/mod.rs | 4 +-- src/vmm/src/arch/x86_64/layout.rs | 2 +- src/vmm/src/builder.rs | 2 +- src/vmm/src/cpu_config/mod.rs | 2 +- src/vmm/src/cpu_config/templates.rs | 2 +- src/vmm/src/cpu_config/test_utils.rs | 2 +- src/vmm/src/devices/legacy/serial.rs | 2 +- src/vmm/src/devices/virtio/balloon/metrics.rs | 2 +- .../devices/virtio/block/virtio/metrics.rs | 3 +- .../devices/virtio/block/virtio/request.rs | 2 +- src/vmm/src/devices/virtio/iovec.rs | 12 ++++---- src/vmm/src/devices/virtio/mmio.rs | 4 +-- src/vmm/src/devices/virtio/net/device.rs | 3 +- src/vmm/src/devices/virtio/net/metrics.rs | 3 +- src/vmm/src/devices/virtio/net/tap.rs | 2 +- src/vmm/src/devices/virtio/queue.rs | 13 ++++---- src/vmm/src/devices/virtio/rng/device.rs | 3 +- src/vmm/src/devices/virtio/rng/metrics.rs | 2 +- src/vmm/src/devices/virtio/test_utils.rs | 2 +- .../src/devices/virtio/vhost_user_metrics.rs | 3 +- .../src/devices/virtio/vsock/event_handler.rs | 2 +- src/vmm/src/devices/virtio/vsock/metrics.rs | 2 +- src/vmm/src/devices/virtio/vsock/packet.rs | 1 + .../src/devices/virtio/vsock/test_utils.rs | 2 +- .../src/devices/virtio/vsock/unix/muxer.rs | 11 +++---- .../devices/virtio/vsock/unix/muxer_rxq.rs | 1 + src/vmm/src/dumbo/pdu/arp.rs | 4 +-- src/vmm/src/dumbo/pdu/bytes.rs | 16 +++++----- src/vmm/src/dumbo/pdu/ethernet.rs | 4 +-- src/vmm/src/dumbo/pdu/ipv4.rs | 4 +-- src/vmm/src/dumbo/pdu/mod.rs | 3 +- src/vmm/src/dumbo/pdu/tcp.rs | 4 +-- src/vmm/src/dumbo/pdu/udp.rs | 4 +-- src/vmm/src/dumbo/tcp/endpoint.rs | 3 +- src/vmm/src/io_uring/mod.rs | 10 +++---- src/vmm/src/lib.rs | 9 ++---- src/vmm/src/logger/metrics.rs | 8 ++--- src/vmm/src/mmds/data_store.rs | 2 +- src/vmm/src/rate_limiter/mod.rs | 16 +++++----- src/vmm/src/resources.rs | 4 +-- src/vmm/src/rpc_interface.rs | 8 ++--- src/vmm/src/vmm_config/boot_source.rs | 2 +- src/vmm/src/vmm_config/net.rs | 6 +--- src/vmm/src/vstate/vcpu/mod.rs | 2 +- 59 files changed, 128 insertions(+), 155 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 914c4cdc87c..4f8cc3f5eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ resolver = "2" [workspace.lints.rust] missing_debug_implementations = "warn" +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] } [workspace.lints.clippy] ptr_as_ptr = "warn" diff --git a/src/acpi-tables/src/aml.rs b/src/acpi-tables/src/aml.rs index 8f839c258e0..69feb5b004f 100644 --- a/src/acpi-tables/src/aml.rs +++ b/src/acpi-tables/src/aml.rs @@ -180,7 +180,7 @@ pub struct Package<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Package<'a> { +impl Aml for Package<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = vec![self.children.len().try_into().unwrap()]; for child in &self.children { @@ -336,7 +336,7 @@ pub struct ResourceTemplate<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for ResourceTemplate<'a> { +impl Aml for ResourceTemplate<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); // Add buffer data @@ -607,7 +607,7 @@ pub struct Device<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Device<'a> { +impl Aml for Device<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -637,7 +637,7 @@ pub struct Scope<'a> { children: Vec<&'a dyn Aml>, } -impl<'a> Aml for Scope<'a> { +impl Aml for Scope<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -678,7 +678,7 @@ impl<'a> Method<'a> { } } -impl<'a> Aml for Method<'a> { +impl Aml for Method<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; @@ -707,7 +707,7 @@ impl<'a> Return<'a> { } } -impl<'a> Aml for Return<'a> { +impl Aml for Return<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0xa4); // ReturnOp self.value.append_aml_bytes(bytes)?; @@ -850,7 +850,7 @@ impl<'a> If<'a> { } } -impl<'a> Aml for If<'a> { +impl Aml for If<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.predicate.append_aml_bytes(&mut tmp)?; @@ -878,7 +878,7 @@ impl<'a> Equal<'a> { } } -impl<'a> Aml for Equal<'a> { +impl Aml for Equal<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x93); // LEqualOp self.left.append_aml_bytes(bytes)?; @@ -898,7 +898,7 @@ impl<'a> LessThan<'a> { } } -impl<'a> Aml for LessThan<'a> { +impl Aml for LessThan<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x95); // LLessOp self.left.append_aml_bytes(bytes)?; @@ -942,7 +942,7 @@ impl<'a> Store<'a> { } } -impl<'a> Aml for Store<'a> { +impl Aml for Store<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x70); // StoreOp self.value.append_aml_bytes(bytes)?; @@ -1023,7 +1023,7 @@ impl<'a> Notify<'a> { } } -impl<'a> Aml for Notify<'a> { +impl Aml for Notify<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x86); // NotifyOp self.object.append_aml_bytes(bytes)?; @@ -1046,7 +1046,7 @@ impl<'a> While<'a> { } } -impl<'a> Aml for While<'a> { +impl Aml for While<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.predicate.append_aml_bytes(&mut tmp)?; @@ -1116,7 +1116,7 @@ impl<'a> MethodCall<'a> { } } -impl<'a> Aml for MethodCall<'a> { +impl Aml for MethodCall<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { self.name.append_aml_bytes(bytes)?; for arg in self.args.iter() { @@ -1169,7 +1169,7 @@ impl<'a, T> CreateField<'a, T> { } } -impl<'a> Aml for CreateField<'a, u64> { +impl Aml for CreateField<'_, u64> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x8f); // CreateQWordFieldOp self.buffer.append_aml_bytes(bytes)?; @@ -1178,7 +1178,7 @@ impl<'a> Aml for CreateField<'a, u64> { } } -impl<'a> Aml for CreateField<'a, u32> { +impl Aml for CreateField<'_, u32> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x8a); // CreateDWordFieldOp self.buffer.append_aml_bytes(bytes)?; diff --git a/src/clippy-tracing/src/main.rs b/src/clippy-tracing/src/main.rs index 61de2eee148..f39382f1324 100644 --- a/src/clippy-tracing/src/main.rs +++ b/src/clippy-tracing/src/main.rs @@ -1,8 +1,6 @@ // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#![warn(clippy::pedantic)] - //! A tool to add, remove and check for `tracing::instrument` in large projects where it is //! infeasible to manually add it to thousands of functions. diff --git a/src/firecracker/src/api_server/request/actions.rs b/src/firecracker/src/api_server/request/actions.rs index 7d7974571a9..a3b3f3f3a88 100644 --- a/src/firecracker/src/api_server/request/actions.rs +++ b/src/firecracker/src/api_server/request/actions.rs @@ -30,9 +30,8 @@ struct ActionBody { pub(crate) fn parse_put_actions(body: &Body) -> Result { METRICS.put_api_requests.actions_count.inc(); - let action_body = serde_json::from_slice::(body.raw()).map_err(|err| { + let action_body = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.actions_fails.inc(); - err })?; match action_body.action_type { diff --git a/src/firecracker/src/api_server/request/boot_source.rs b/src/firecracker/src/api_server/request/boot_source.rs index 16f3c1b5499..10e16148461 100644 --- a/src/firecracker/src/api_server/request/boot_source.rs +++ b/src/firecracker/src/api_server/request/boot_source.rs @@ -11,9 +11,8 @@ use super::Body; pub(crate) fn parse_put_boot_source(body: &Body) -> Result { METRICS.put_api_requests.boot_source_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::ConfigureBootSource( - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.boot_source_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/drive.rs b/src/firecracker/src/api_server/request/drive.rs index a74d3be69ff..4b2548b53c8 100644 --- a/src/firecracker/src/api_server/request/drive.rs +++ b/src/firecracker/src/api_server/request/drive.rs @@ -20,9 +20,8 @@ pub(crate) fn parse_put_drive( return Err(RequestError::EmptyID); }; - let device_cfg = serde_json::from_slice::(body.raw()).map_err(|err| { + let device_cfg = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.drive_fails.inc(); - err })?; if id != device_cfg.drive_id { @@ -51,9 +50,8 @@ pub(crate) fn parse_patch_drive( }; let block_device_update_cfg: BlockDeviceUpdateConfig = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.drive_fails.inc(); - err })?; if id != block_device_update_cfg.drive_id { diff --git a/src/firecracker/src/api_server/request/logger.rs b/src/firecracker/src/api_server/request/logger.rs index 6355bf48beb..cda125ac71c 100644 --- a/src/firecracker/src/api_server/request/logger.rs +++ b/src/firecracker/src/api_server/request/logger.rs @@ -10,9 +10,8 @@ use super::Body; pub(crate) fn parse_put_logger(body: &Body) -> Result { METRICS.put_api_requests.logger_count.inc(); let res = serde_json::from_slice::(body.raw()); - let config = res.map_err(|err| { + let config = res.inspect_err(|_| { METRICS.put_api_requests.logger_fails.inc(); - err })?; Ok(ParsedRequest::new_sync(VmmAction::ConfigureLogger(config))) } diff --git a/src/firecracker/src/api_server/request/machine_configuration.rs b/src/firecracker/src/api_server/request/machine_configuration.rs index 344d9095b77..871bbda5ecc 100644 --- a/src/firecracker/src/api_server/request/machine_configuration.rs +++ b/src/firecracker/src/api_server/request/machine_configuration.rs @@ -15,9 +15,8 @@ pub(crate) fn parse_get_machine_config() -> Result pub(crate) fn parse_put_machine_config(body: &Body) -> Result { METRICS.put_api_requests.machine_cfg_count.inc(); - let config = serde_json::from_slice::(body.raw()).map_err(|err| { + let config = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.machine_cfg_fails.inc(); - err })?; // Check for the presence of deprecated `cpu_template` field. @@ -44,9 +43,8 @@ pub(crate) fn parse_put_machine_config(body: &Body) -> Result Result { METRICS.patch_api_requests.machine_cfg_count.inc(); let config_update = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.machine_cfg_fails.inc(); - err })?; if config_update.is_empty() { diff --git a/src/firecracker/src/api_server/request/metrics.rs b/src/firecracker/src/api_server/request/metrics.rs index e6b361a49c1..054ece19422 100644 --- a/src/firecracker/src/api_server/request/metrics.rs +++ b/src/firecracker/src/api_server/request/metrics.rs @@ -11,9 +11,8 @@ use super::Body; pub(crate) fn parse_put_metrics(body: &Body) -> Result { METRICS.put_api_requests.metrics_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::ConfigureMetrics( - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.metrics_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/mmds.rs b/src/firecracker/src/api_server/request/mmds.rs index ced0a671e9b..2bc96512d3c 100644 --- a/src/firecracker/src/api_server/request/mmds.rs +++ b/src/firecracker/src/api_server/request/mmds.rs @@ -16,9 +16,8 @@ pub(crate) fn parse_get_mmds() -> Result { } fn parse_put_mmds_config(body: &Body) -> Result { - let config: MmdsConfig = serde_json::from_slice(body.raw()).map_err(|err| { + let config: MmdsConfig = serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.put_api_requests.mmds_fails.inc(); - err })?; // Construct the `ParsedRequest` object. let version = config.version; @@ -42,9 +41,8 @@ pub(crate) fn parse_put_mmds( METRICS.put_api_requests.mmds_count.inc(); match path_second_token { None => Ok(ParsedRequest::new_sync(VmmAction::PutMMDS( - serde_json::from_slice(body.raw()).map_err(|err| { + serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.put_api_requests.mmds_fails.inc(); - err })?, ))), Some("config") => parse_put_mmds_config(body), @@ -61,9 +59,8 @@ pub(crate) fn parse_put_mmds( pub(crate) fn parse_patch_mmds(body: &Body) -> Result { METRICS.patch_api_requests.mmds_count.inc(); Ok(ParsedRequest::new_sync(VmmAction::PatchMMDS( - serde_json::from_slice(body.raw()).map_err(|err| { + serde_json::from_slice(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.mmds_fails.inc(); - err })?, ))) } diff --git a/src/firecracker/src/api_server/request/net.rs b/src/firecracker/src/api_server/request/net.rs index 0ab5377b0a1..5fced98635c 100644 --- a/src/firecracker/src/api_server/request/net.rs +++ b/src/firecracker/src/api_server/request/net.rs @@ -20,9 +20,8 @@ pub(crate) fn parse_put_net( return Err(RequestError::EmptyID); }; - let netif = serde_json::from_slice::(body.raw()).map_err(|err| { + let netif = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.network_fails.inc(); - err })?; if id != netif.iface_id.as_str() { METRICS.put_api_requests.network_fails.inc(); @@ -53,9 +52,8 @@ pub(crate) fn parse_patch_net( }; let netif = - serde_json::from_slice::(body.raw()).map_err(|err| { + serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.patch_api_requests.network_fails.inc(); - err })?; if id != netif.iface_id { METRICS.patch_api_requests.network_count.inc(); diff --git a/src/firecracker/src/api_server/request/vsock.rs b/src/firecracker/src/api_server/request/vsock.rs index 67bf7b0a985..acf129d456c 100644 --- a/src/firecracker/src/api_server/request/vsock.rs +++ b/src/firecracker/src/api_server/request/vsock.rs @@ -10,9 +10,8 @@ use super::Body; pub(crate) fn parse_put_vsock(body: &Body) -> Result { METRICS.put_api_requests.vsock_count.inc(); - let vsock_cfg = serde_json::from_slice::(body.raw()).map_err(|err| { + let vsock_cfg = serde_json::from_slice::(body.raw()).inspect_err(|_| { METRICS.put_api_requests.vsock_fails.inc(); - err })?; // Check for the presence of deprecated `vsock_id` field. diff --git a/src/seccompiler/src/backend.rs b/src/seccompiler/src/backend.rs index cc4b1d4c9e3..22de1cee501 100644 --- a/src/seccompiler/src/backend.rs +++ b/src/seccompiler/src/backend.rs @@ -868,7 +868,7 @@ mod tests { } impl SeccompCondition { - // Creates a new `SeccompCondition`. + /// Creates a new `SeccompCondition`. pub fn new( arg_number: u8, arg_len: SeccompCmpArgLen, diff --git a/src/seccompiler/src/compiler.rs b/src/seccompiler/src/compiler.rs index 73ff9f706ca..9194bc7e5bd 100644 --- a/src/seccompiler/src/compiler.rs +++ b/src/seccompiler/src/compiler.rs @@ -258,7 +258,7 @@ mod tests { }; impl Filter { - pub fn new( + fn new( default_action: SeccompAction, filter_action: SeccompAction, filter: Vec, @@ -272,7 +272,7 @@ mod tests { } impl SyscallRule { - pub fn new(syscall: String, conditions: Option>) -> SyscallRule { + fn new(syscall: String, conditions: Option>) -> SyscallRule { SyscallRule { syscall, conditions, diff --git a/src/vmm/benches/queue.rs b/src/vmm/benches/queue.rs index faff57b2ebf..1d19bcd3973 100644 --- a/src/vmm/benches/queue.rs +++ b/src/vmm/benches/queue.rs @@ -88,7 +88,7 @@ pub fn queue_benchmark(c: &mut Criterion) { for i in 0_u16..16_u16 { let index = std::hint::black_box(i); let len = std::hint::black_box(i + 1); - _ = queue.add_used(index as u16, len as u32); + _ = queue.add_used(index, len as u32); } }) }); @@ -100,7 +100,7 @@ pub fn queue_benchmark(c: &mut Criterion) { for i in 0_u16..256_u16 { let index = std::hint::black_box(i); let len = std::hint::black_box(i + 1); - _ = queue.add_used(index as u16, len as u32); + _ = queue.add_used(index, len as u32); } }) }); diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index 247c832e665..9542fad3902 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -48,7 +48,7 @@ struct AcpiTableWriter<'a> { resource_allocator: &'a mut ResourceAllocator, } -impl<'a> AcpiTableWriter<'a> { +impl AcpiTableWriter<'_> { /// Write a table in guest memory /// /// This will allocate enough space inside guest memory and write the table in the allocated @@ -181,7 +181,7 @@ pub(crate) fn create_acpi_tables( } #[cfg(test)] -pub mod tests { +mod tests { use acpi_tables::Sdt; use vm_memory::Bytes; diff --git a/src/vmm/src/arch/x86_64/layout.rs b/src/vmm/src/arch/x86_64/layout.rs index 01355b3018a..1e50bb9c235 100644 --- a/src/vmm/src/arch/x86_64/layout.rs +++ b/src/vmm/src/arch/x86_64/layout.rs @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -/// Magic addresses externally used to lay out x86_64 VMs. +//! Magic addresses externally used to lay out x86_64 VMs. /// Initial stack for the boot CPU. pub const BOOT_STACK_POINTER: u64 = 0x8ff0; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 3355633e3c8..8594da9f077 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -1023,7 +1023,7 @@ pub(crate) fn set_stdout_nonblocking() { } #[cfg(test)] -pub mod tests { +pub(crate) mod tests { use std::io::Write; use linux_loader::cmdline::Cmdline; diff --git a/src/vmm/src/cpu_config/mod.rs b/src/vmm/src/cpu_config/mod.rs index 3e438d07ef4..4c7404a14d3 100644 --- a/src/vmm/src/cpu_config/mod.rs +++ b/src/vmm/src/cpu_config/mod.rs @@ -15,4 +15,4 @@ pub mod x86_64; pub mod aarch64; #[cfg(test)] -pub mod test_utils; +pub(crate) mod test_utils; diff --git a/src/vmm/src/cpu_config/templates.rs b/src/vmm/src/cpu_config/templates.rs index 984fd8dcac2..fa883964ed8 100644 --- a/src/vmm/src/cpu_config/templates.rs +++ b/src/vmm/src/cpu_config/templates.rs @@ -83,7 +83,7 @@ impl From<&CpuTemplateType> for StaticCpuTemplate { } } -impl<'a> TryFrom<&'a [u8]> for CustomCpuTemplate { +impl TryFrom<&[u8]> for CustomCpuTemplate { type Error = serde_json::Error; fn try_from(value: &[u8]) -> Result { diff --git a/src/vmm/src/cpu_config/test_utils.rs b/src/vmm/src/cpu_config/test_utils.rs index de2e952522e..197c0c62cf6 100644 --- a/src/vmm/src/cpu_config/test_utils.rs +++ b/src/vmm/src/cpu_config/test_utils.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use crate::cpu_config::templates::CustomCpuTemplate; -// Get a static CPU template stored as a JSON file. +/// Get a static CPU template stored as a JSON file. pub fn get_json_template(filename: &str) -> CustomCpuTemplate { let json_path = [ env!("CARGO_MANIFEST_DIR"), diff --git a/src/vmm/src/devices/legacy/serial.rs b/src/vmm/src/devices/legacy/serial.rs index cd74159dbdc..278c15a4464 100644 --- a/src/vmm/src/devices/legacy/serial.rs +++ b/src/vmm/src/devices/legacy/serial.rs @@ -386,7 +386,7 @@ mod tests { ), input: None::, }; - serial.serial.raw_input(&[b'a', b'b', b'c']).unwrap(); + serial.serial.raw_input(b"abc").unwrap(); let invalid_reads_before = metrics.missed_read_count.count(); let mut v = [0x00; 2]; diff --git a/src/vmm/src/devices/virtio/balloon/metrics.rs b/src/vmm/src/devices/virtio/balloon/metrics.rs index da8f7a28520..0b438cae2d4 100644 --- a/src/vmm/src/devices/virtio/balloon/metrics.rs +++ b/src/vmm/src/devices/virtio/balloon/metrics.rs @@ -31,7 +31,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/block/virtio/metrics.rs b/src/vmm/src/devices/virtio/block/virtio/metrics.rs index 69a521fde54..0abe2a58963 100644 --- a/src/vmm/src/devices/virtio/block/virtio/metrics.rs +++ b/src/vmm/src/devices/virtio/block/virtio/metrics.rs @@ -72,7 +72,8 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! //! We add BlockDeviceMetrics entries from block::metrics::METRICS into Block device instead of //! Block device having individual separate BlockDeviceMetrics entries because Block device is not //! accessible from signal handlers to flush metrics and block::metrics::METRICS is. diff --git a/src/vmm/src/devices/virtio/block/virtio/request.rs b/src/vmm/src/devices/virtio/block/virtio/request.rs index 4eb8d7e2efd..27df7c1d675 100644 --- a/src/vmm/src/devices/virtio/block/virtio/request.rs +++ b/src/vmm/src/devices/virtio/block/virtio/request.rs @@ -467,7 +467,7 @@ mod tests { assert_eq!(RequestType::from(42), RequestType::Unsupported(42)); } - impl<'a, 'b> RequestDescriptorChain<'a, 'b> { + impl RequestDescriptorChain<'_, '_> { fn check_parse_err(&self, _e: VirtioBlockError) { let mut q = self.driver_queue.create_queue(); let memory = self.driver_queue.memory(); diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index 2161d7273ef..9262dff661b 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -264,10 +264,11 @@ impl IoVecBufferMut { // We use get_slice instead of `get_host_address` here in order to have the whole // range of the descriptor chain checked, i.e. [addr, addr + len) is a valid memory // region in the GuestMemoryMmap. - let slice = mem.get_slice(desc.addr, desc.len as usize).map_err(|err| { - self.vecs.pop_back(nr_iovecs); - err - })?; + let slice = mem + .get_slice(desc.addr, desc.len as usize) + .inspect_err(|_| { + self.vecs.pop_back(nr_iovecs); + })?; // We need to mark the area of guest memory that will be mutated through this // IoVecBufferMut as dirty ahead of time, as we loose access to all // vm-memory related information after converting down to iovecs. @@ -288,9 +289,8 @@ impl IoVecBufferMut { length = length .checked_add(desc.len) .ok_or(IoVecError::OverflowedDescriptor) - .map_err(|err| { + .inspect_err(|_| { self.vecs.pop_back(nr_iovecs); - err })?; next_descriptor = desc.next_descriptor(); diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs index f734058c5b1..63d7a80d84d 100644 --- a/src/vmm/src/devices/virtio/mmio.rs +++ b/src/vmm/src/devices/virtio/mmio.rs @@ -38,9 +38,9 @@ const MMIO_VERSION: u32 = 2; /// /// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base. /// 1. `Mmio::queue_evts` must be installed at `virtio::NOTIFY_REG_OFFSET` offset from the MMIO -/// base. Each event in the array must be signaled if the index is written at that offset. +/// base. Each event in the array must be signaled if the index is written at that offset. /// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it -/// is written to. +/// is written to. /// /// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport /// and inner virtio device. diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 818fed86a30..a17c25d7248 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -514,10 +514,9 @@ impl Net { NetError::VnetHeaderMissing })?; - let headers = frame_bytes_from_buf(&headers[..header_len]).map_err(|e| { + let headers = frame_bytes_from_buf(&headers[..header_len]).inspect_err(|_| { error!("VNET headers missing in TX frame"); net_metrics.tx_malformed_frames.inc(); - e })?; if let Some(ns) = mmds_ns { diff --git a/src/vmm/src/devices/virtio/net/metrics.rs b/src/vmm/src/devices/virtio/net/metrics.rs index dfdf69702a7..60e03f224de 100644 --- a/src/vmm/src/devices/virtio/net/metrics.rs +++ b/src/vmm/src/devices/virtio/net/metrics.rs @@ -75,7 +75,8 @@ //! //! The system implements 1 types of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! //! We use net::metrics::METRICS instead of adding an entry of NetDeviceMetrics //! in Net so that metrics are accessible to be flushed even from signal handlers. diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 32c665e1c31..0f5b7e2d788 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -122,7 +122,7 @@ impl Tap { // string and verify the result. let fd = unsafe { libc::open( - b"/dev/net/tun\0".as_ptr().cast::(), + c"/dev/net/tun".as_ptr(), libc::O_RDWR | libc::O_NONBLOCK | libc::O_CLOEXEC, ) }; diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs index 39ccef1f1ee..7c2c78d2407 100644 --- a/src/vmm/src/devices/virtio/queue.rs +++ b/src/vmm/src/devices/virtio/queue.rs @@ -172,9 +172,8 @@ impl Iterator for DescriptorIterator { type Item = DescriptorChain; fn next(&mut self) -> Option { - self.0.take().map(|desc| { + self.0.take().inspect(|desc| { self.0 = desc.next_descriptor(); - desc }) } } @@ -560,10 +559,9 @@ impl Queue { // index is bound by the queue size let desc_index = unsafe { self.avail_ring_ring_get(usize::from(idx)) }; - DescriptorChain::checked_new(self.desc_table_ptr, self.actual_size(), desc_index).map( - |dc| { + DescriptorChain::checked_new(self.desc_table_ptr, self.actual_size(), desc_index).inspect( + |_| { self.next_avail += Wrapping(1); - dc }, ) } @@ -575,9 +573,8 @@ impl Queue { } /// Write used element into used_ring ring. - /// - [`ring_index_offset`] is an offset added to - /// the current [`self.next_used`] to obtain actual index - /// into used_ring. + /// - [`ring_index_offset`] is an offset added to the current [`self.next_used`] to obtain + /// actual index into used_ring. pub fn write_used_element( &mut self, ring_index_offset: u16, diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs index 96513e49b26..dca25999f3e 100644 --- a/src/vmm/src/devices/virtio/rng/device.rs +++ b/src/vmm/src/devices/virtio/rng/device.rs @@ -119,9 +119,8 @@ impl Entropy { } let mut rand_bytes = vec![0; self.buffer.len() as usize]; - rand::fill(&mut rand_bytes).map_err(|err| { + rand::fill(&mut rand_bytes).inspect_err(|_| { METRICS.host_rng_fails.inc(); - err })?; // It is ok to unwrap here. We are writing `iovec.len()` bytes at offset 0. diff --git a/src/vmm/src/devices/virtio/rng/metrics.rs b/src/vmm/src/devices/virtio/rng/metrics.rs index eb1dcbfacae..e02f5ce8cc4 100644 --- a/src/vmm/src/devices/virtio/rng/metrics.rs +++ b/src/vmm/src/devices/virtio/rng/metrics.rs @@ -31,7 +31,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/test_utils.rs b/src/vmm/src/devices/virtio/test_utils.rs index 9bb66db82ae..aa1ede08e58 100644 --- a/src/vmm/src/devices/virtio/test_utils.rs +++ b/src/vmm/src/devices/virtio/test_utils.rs @@ -377,7 +377,7 @@ pub(crate) mod test { const QUEUE_SIZE: u16 = 16; // Helper function to create a set of Virtqueues for the device - fn create_virtqueues(mem: &'a GuestMemoryMmap, num_queues: usize) -> Vec { + fn create_virtqueues(mem: &'a GuestMemoryMmap, num_queues: usize) -> Vec> { (0..num_queues) .scan(GuestAddress(0), |next_addr, _| { let vqueue = VirtQueue::new(*next_addr, mem, Self::QUEUE_SIZE); diff --git a/src/vmm/src/devices/virtio/vhost_user_metrics.rs b/src/vmm/src/devices/virtio/vhost_user_metrics.rs index 73b41e6a86c..0a3c8cd3a6a 100644 --- a/src/vmm/src/devices/virtio/vhost_user_metrics.rs +++ b/src/vmm/src/devices/virtio/vhost_user_metrics.rs @@ -64,9 +64,10 @@ //! //! The system implements 2 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times activating a device failed). These metrics are reset upon flush. +//! (i.e the number of times activating a device failed). These metrics are reset upon flush. //! * Shared Store Metrics (SharedStoreMetrics) - are targeted at keeping a persistent value, it is //! `not` intended to act as a counter (i.e for measure the process start up time for example). +//! //! We add VhostUserDeviceMetrics entries from vhost_user_metrics::METRICS into vhost_user device //! instead of vhost_user device having individual separate VhostUserDeviceMetrics entries because //! vhost_user device is not accessible from signal handlers to flush metrics and diff --git a/src/vmm/src/devices/virtio/vsock/event_handler.rs b/src/vmm/src/devices/virtio/vsock/event_handler.rs index 40e75d1a9f5..59cf3fe0103 100755 --- a/src/vmm/src/devices/virtio/vsock/event_handler.rs +++ b/src/vmm/src/devices/virtio/vsock/event_handler.rs @@ -9,7 +9,7 @@ use std::fmt::Debug; /// The vsock object implements the runtime logic of our vsock device: /// 1. Respond to TX queue events by wrapping virtio buffers into `VsockPacket`s, then sending -/// those packets to the `VsockBackend`; +/// those packets to the `VsockBackend`; /// 2. Forward backend FD event notifications to the `VsockBackend`; /// 3. Fetch incoming packets from the `VsockBackend` and place them into the virtio RX queue; /// 4. Whenever we have processed some virtio buffers (either TX or RX), let the driver know by diff --git a/src/vmm/src/devices/virtio/vsock/metrics.rs b/src/vmm/src/devices/virtio/vsock/metrics.rs index 5307302f5ca..d626d5dca34 100644 --- a/src/vmm/src/devices/virtio/vsock/metrics.rs +++ b/src/vmm/src/devices/virtio/vsock/metrics.rs @@ -34,7 +34,7 @@ //! //! The system implements 1 type of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; diff --git a/src/vmm/src/devices/virtio/vsock/packet.rs b/src/vmm/src/devices/virtio/vsock/packet.rs index 213b5bb2b34..f19723d25cb 100644 --- a/src/vmm/src/devices/virtio/vsock/packet.rs +++ b/src/vmm/src/devices/virtio/vsock/packet.rs @@ -7,6 +7,7 @@ //! virtio queue: //! - the packet header; and //! - the packet data/buffer. +//! //! There is a 1:1 relation between descriptor chains and packets: the first (chain head) holds //! the header, and an optional second descriptor holds the data. The second descriptor is only //! present for data packets (VSOCK_OP_RW). diff --git a/src/vmm/src/devices/virtio/vsock/test_utils.rs b/src/vmm/src/devices/virtio/vsock/test_utils.rs index 4a5fdb2c941..804f0442559 100644 --- a/src/vmm/src/devices/virtio/vsock/test_utils.rs +++ b/src/vmm/src/devices/virtio/vsock/test_utils.rs @@ -190,7 +190,7 @@ pub struct EventHandlerContext<'a> { pub guest_evvq: GuestQ<'a>, } -impl<'a> EventHandlerContext<'a> { +impl EventHandlerContext<'_> { pub fn mock_activate(&mut self, mem: GuestMemoryMmap) { // Artificially activate the device. self.device.activate(mem).unwrap(); diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs index 4d4b1996237..84273f45aba 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs @@ -24,11 +24,12 @@ /// destination port to which it wants to connect); /// 3. Some event was triggered for a connected Unix socket, that belongs to a /// `VsockConnection`. -/// The muxer gets notified about all of these events, because, as a `VsockEpollListener` -/// implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All -/// other pollable FDs are then registered under this nested epoll FD. -/// To route all these events to their handlers, the muxer uses another `HashMap` object, -/// mapping `RawFd`s to `EpollListener`s. +/// +/// The muxer gets notified about all of these events, because, as a `VsockEpollListener` +/// implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All +/// other pollable FDs are then registered under this nested epoll FD. +/// To route all these events to their handlers, the muxer uses another `HashMap` object, +/// mapping `RawFd`s to `EpollListener`s. use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::io::Read; diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs index 8327882a3fb..77f7670af7d 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs @@ -67,6 +67,7 @@ impl MuxerRxQ { /// A push will fail when: /// - trying to push a connection key onto an out-of-sync, or full queue; or /// - trying to push an RST onto a queue already full of RSTs. + /// /// RSTs take precedence over connections, because connections can always be queried for /// pending RX data later. Aside from this queue, there is no other storage for RSTs, so /// failing to push one means that we have to drop the packet. diff --git a/src/vmm/src/dumbo/pdu/arp.rs b/src/vmm/src/dumbo/pdu/arp.rs index bccb32154a9..54286d281b7 100644 --- a/src/vmm/src/dumbo/pdu/arp.rs +++ b/src/vmm/src/dumbo/pdu/arp.rs @@ -71,7 +71,7 @@ pub struct EthIPv4ArpFrame<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> EthIPv4ArpFrame<'a, T> { +impl EthIPv4ArpFrame<'_, T> { /// Interprets the given bytes as an ARP frame, without doing any validity checks beforehand. /// /// # Panics @@ -184,7 +184,7 @@ impl<'a, T: NetworkBytes + Debug> EthIPv4ArpFrame<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> EthIPv4ArpFrame<'a, T> { +impl EthIPv4ArpFrame<'_, T> { #[allow(clippy::too_many_arguments)] fn write_raw( buf: T, diff --git a/src/vmm/src/dumbo/pdu/bytes.rs b/src/vmm/src/dumbo/pdu/bytes.rs index 9b87673c211..7d5e2346428 100644 --- a/src/vmm/src/dumbo/pdu/bytes.rs +++ b/src/vmm/src/dumbo/pdu/bytes.rs @@ -134,20 +134,20 @@ pub trait NetworkBytesMut: NetworkBytes + DerefMut { } } -impl<'a> NetworkBytes for &'a [u8] { +impl NetworkBytes for &[u8] { #[inline] fn shrink_unchecked(&mut self, len: usize) { *self = &self[..len]; } } -impl<'a> NetworkBytes for &'a mut [u8] { +impl NetworkBytes for &mut [u8] { #[inline] fn shrink_unchecked(&mut self, len: usize) { *self = &mut std::mem::take(self)[..len]; } } -impl<'a> NetworkBytesMut for &'a mut [u8] {} +impl NetworkBytesMut for &mut [u8] {} // This struct is used as a convenience for any type which contains a generic member implementing // NetworkBytes with a lifetime, so we don't have to also add the PhantomData member each time. We @@ -158,7 +158,7 @@ pub(super) struct InnerBytes<'a, T: 'a> { phantom: PhantomData<&'a T>, } -impl<'a, T: Debug> InnerBytes<'a, T> { +impl InnerBytes<'_, T> { /// Creates a new instance as a wrapper around `bytes`. #[inline] pub fn new(bytes: T) -> Self { @@ -169,7 +169,7 @@ impl<'a, T: Debug> InnerBytes<'a, T> { } } -impl<'a, T: Deref + Debug> Deref for InnerBytes<'a, T> { +impl + Debug> Deref for InnerBytes<'_, T> { type Target = [u8]; #[inline] @@ -178,21 +178,21 @@ impl<'a, T: Deref + Debug> Deref for InnerBytes<'a, T> { } } -impl<'a, T: DerefMut + Debug> DerefMut for InnerBytes<'a, T> { +impl + Debug> DerefMut for InnerBytes<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut [u8] { self.bytes.deref_mut() } } -impl<'a, T: NetworkBytes + Debug> NetworkBytes for InnerBytes<'a, T> { +impl NetworkBytes for InnerBytes<'_, T> { #[inline] fn shrink_unchecked(&mut self, len: usize) { self.bytes.shrink_unchecked(len); } } -impl<'a, T: NetworkBytesMut + Debug> NetworkBytesMut for InnerBytes<'a, T> {} +impl NetworkBytesMut for InnerBytes<'_, T> {} #[cfg(test)] mod tests { diff --git a/src/vmm/src/dumbo/pdu/ethernet.rs b/src/vmm/src/dumbo/pdu/ethernet.rs index 8b3321ca4b8..f93a0c5d007 100644 --- a/src/vmm/src/dumbo/pdu/ethernet.rs +++ b/src/vmm/src/dumbo/pdu/ethernet.rs @@ -40,7 +40,7 @@ pub struct EthernetFrame<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> EthernetFrame<'a, T> { +impl EthernetFrame<'_, T> { /// Interprets `bytes` as an Ethernet frame without any validity checks. /// /// # Panics @@ -101,7 +101,7 @@ impl<'a, T: NetworkBytes + Debug> EthernetFrame<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> EthernetFrame<'a, T> { +impl EthernetFrame<'_, T> { /// Attempts to write an Ethernet frame using the given header fields to `buf`. fn new_with_header( buf: T, diff --git a/src/vmm/src/dumbo/pdu/ipv4.rs b/src/vmm/src/dumbo/pdu/ipv4.rs index 20d7694524e..f3da2b7b298 100644 --- a/src/vmm/src/dumbo/pdu/ipv4.rs +++ b/src/vmm/src/dumbo/pdu/ipv4.rs @@ -62,7 +62,7 @@ pub struct IPv4Packet<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> IPv4Packet<'a, T> { +impl IPv4Packet<'_, T> { /// Interpret `bytes` as an IPv4Packet without checking the validity of the header fields, and /// the length of the inner byte sequence. /// @@ -250,7 +250,7 @@ impl<'a, T: NetworkBytes + Debug> IPv4Packet<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> IPv4Packet<'a, T> { +impl IPv4Packet<'_, T> { /// Attempts to write an IPv4 packet header to `buf`, making sure there is enough space. /// /// This method returns an incomplete packet, because the size of the payload might be unknown diff --git a/src/vmm/src/dumbo/pdu/mod.rs b/src/vmm/src/dumbo/pdu/mod.rs index d700474ed02..fc6a24760a7 100644 --- a/src/vmm/src/dumbo/pdu/mod.rs +++ b/src/vmm/src/dumbo/pdu/mod.rs @@ -66,8 +66,7 @@ enum ChecksumProto { /// * `bytes` - Raw bytes of a TCP packet or a UDP datagram /// * `src_addr` - IPv4 source address /// * `dst_addr` - IPv4 destination address -/// * `protocol` - **must** be either `PROTOCOL_TCP` or `PROTOCOL_UDP` defined in -/// `ipv4` module +/// * `protocol` - **must** be either `PROTOCOL_TCP` or `PROTOCOL_UDP` defined in `ipv4` module /// /// More details about TCP checksum computation can be found [here]. /// diff --git a/src/vmm/src/dumbo/pdu/tcp.rs b/src/vmm/src/dumbo/pdu/tcp.rs index 2a884689f83..d5eade0c644 100644 --- a/src/vmm/src/dumbo/pdu/tcp.rs +++ b/src/vmm/src/dumbo/pdu/tcp.rs @@ -99,7 +99,7 @@ pub struct TcpSegment<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> TcpSegment<'a, T> { +impl TcpSegment<'_, T> { /// Returns the source port. #[inline] pub fn source_port(&self) -> u16 { @@ -314,7 +314,7 @@ impl<'a, T: NetworkBytes + Debug> TcpSegment<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> TcpSegment<'a, T> { +impl TcpSegment<'_, T> { /// Sets the source port. #[inline] pub fn set_source_port(&mut self, value: u16) -> &mut Self { diff --git a/src/vmm/src/dumbo/pdu/udp.rs b/src/vmm/src/dumbo/pdu/udp.rs index 43ad9c29cef..8acfc4509f4 100644 --- a/src/vmm/src/dumbo/pdu/udp.rs +++ b/src/vmm/src/dumbo/pdu/udp.rs @@ -46,7 +46,7 @@ pub struct UdpDatagram<'a, T: 'a> { } #[allow(clippy::len_without_is_empty)] -impl<'a, T: NetworkBytes + Debug> UdpDatagram<'a, T> { +impl UdpDatagram<'_, T> { /// Interprets `bytes` as a UDP datagram without any validity checks. /// /// # Panics @@ -122,7 +122,7 @@ impl<'a, T: NetworkBytes + Debug> UdpDatagram<'a, T> { } } -impl<'a, T: NetworkBytesMut + Debug> UdpDatagram<'a, T> { +impl UdpDatagram<'_, T> { /// Writes an incomplete UDP datagram, which is missing the `checksum`, `src_port` and /// `dst_port` fields. /// diff --git a/src/vmm/src/dumbo/tcp/endpoint.rs b/src/vmm/src/dumbo/tcp/endpoint.rs index 92058d83ee9..15fb10e10f9 100644 --- a/src/vmm/src/dumbo/tcp/endpoint.rs +++ b/src/vmm/src/dumbo/tcp/endpoint.rs @@ -281,9 +281,8 @@ impl Endpoint { tcp_payload_src, timestamp_cycles(), ) { - Ok(write_result) => write_result.map(|segment| { + Ok(write_result) => write_result.inspect(|segment| { self.response_seq += Wrapping(u32::from(segment.inner().payload_len())); - segment }), Err(_) => { METRICS.mmds.tx_errors.inc(); diff --git a/src/vmm/src/io_uring/mod.rs b/src/vmm/src/io_uring/mod.rs index 3466fd01aa5..f306148044c 100644 --- a/src/vmm/src/io_uring/mod.rs +++ b/src/vmm/src/io_uring/mod.rs @@ -97,8 +97,8 @@ impl IoUring { /// /// # Arguments /// - /// * `num_entries` - Requested number of entries in the ring. Will be rounded up to the - /// nearest power of two. + /// * `num_entries` - Requested number of entries in the ring. Will be rounded up to the nearest + /// power of two. /// * `files` - Files to be registered for IO. /// * `restrictions` - Vector of [`Restriction`](restriction/enum.Restriction.html)s /// * `eventfd` - Optional eventfd for receiving completion notifications. @@ -175,10 +175,9 @@ impl IoUring { } self.squeue .push(op.into_sqe(&mut self.slab)) - .map(|res| { + .inspect(|_| { // This is safe since self.num_ops < IORING_MAX_CQ_ENTRIES (65536) self.num_ops += 1; - res }) .map_err(|(sqe_err, user_data_key)| -> (IoUringError, T) { ( @@ -207,11 +206,10 @@ impl IoUring { self.cqueue .pop(&mut self.slab) .map(|maybe_cqe| { - maybe_cqe.map(|cqe| { + maybe_cqe.inspect(|_| { // This is safe since the pop-ed CQEs have been previously pushed. However // we use a saturating_sub for extra safety. self.num_ops = self.num_ops.saturating_sub(1); - cqe }) }) .map_err(IoUringError::CQueue) diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index c80f004e789..6a28e14f26b 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -368,15 +368,13 @@ impl Vmm { if let Some(stdin) = self.events_observer.as_mut() { // Set raw mode for stdin. - stdin.lock().set_raw_mode().map_err(|err| { + stdin.lock().set_raw_mode().inspect_err(|&err| { warn!("Cannot set raw mode for the terminal. {:?}", err); - err })?; // Set non blocking stdin. - stdin.lock().set_non_block(true).map_err(|err| { + stdin.lock().set_non_block(true).inspect_err(|&err| { warn!("Cannot set non block for the terminal. {:?}", err); - err })?; } @@ -906,9 +904,8 @@ impl Drop for Vmm { self.stop(self.shutdown_exit_code.unwrap_or(FcExitCode::Ok)); if let Some(observer) = self.events_observer.as_mut() { - let res = observer.lock().set_canon_mode().map_err(|err| { + let res = observer.lock().set_canon_mode().inspect_err(|&err| { warn!("Cannot set canonical mode for the terminal. {:?}", err); - err }); if let Err(err) = res { warn!("{}", VmmError::VmmObserverTeardown(err)); diff --git a/src/vmm/src/logger/metrics.rs b/src/vmm/src/logger/metrics.rs index bcde569115e..a911a53e8a9 100644 --- a/src/vmm/src/logger/metrics.rs +++ b/src/vmm/src/logger/metrics.rs @@ -46,10 +46,9 @@ //! //! The system implements 2 types of metrics: //! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter -//! (i.e the number of times an API request failed). These metrics are reset upon flush. +//! (i.e the number of times an API request failed). These metrics are reset upon flush. //! * Shared Store Metrics (SharedStoreMetrics) - are targeted at keeping a persistent value, it is -//! not -//! intended to act as a counter (i.e for measure the process start up time for example). +//! not intended to act as a counter (i.e for measure the process start up time for example). //! //! The current approach for the `SharedIncMetrics` type is to store two values (current and //! previous) and compute the delta between them each time we do a flush (i.e by serialization). @@ -58,6 +57,7 @@ //! to actual writing, so less synchronization effort is required. //! * We don't have to worry at all that much about losing some data if writing fails for a while //! (this could be a concern, I guess). +//! //! If if turns out this approach is not really what we want, it's pretty easy to resort to //! something else, while working behind the same interface. @@ -706,7 +706,7 @@ impl<'a> LatencyMetricsRecorder<'a> { } } } -impl<'a> Drop for LatencyMetricsRecorder<'a> { +impl Drop for LatencyMetricsRecorder<'_> { /// records aggregate (min/max/sum) for the given metric /// This captures delta between self.start_time and current time /// and updates min/max/sum metrics. diff --git a/src/vmm/src/mmds/data_store.rs b/src/vmm/src/mmds/data_store.rs index 1cbb2dfd088..41fe297ab06 100644 --- a/src/vmm/src/mmds/data_store.rs +++ b/src/vmm/src/mmds/data_store.rs @@ -281,7 +281,7 @@ mod tests { use super::*; impl Mmds { - pub fn get_data_str(&self) -> String { + fn get_data_str(&self) -> String { if self.data_store.is_null() { return String::from("{}"); } diff --git a/src/vmm/src/rate_limiter/mod.rs b/src/vmm/src/rate_limiter/mod.rs index b4c2a6d34ed..3ed5405bf01 100644 --- a/src/vmm/src/rate_limiter/mod.rs +++ b/src/vmm/src/rate_limiter/mod.rs @@ -328,15 +328,15 @@ impl RateLimiter { /// # Arguments /// /// * `bytes_total_capacity` - the total capacity of the `TokenType::Bytes` token bucket. - /// * `bytes_one_time_burst` - initial extra credit on top of `bytes_total_capacity`, - /// that does not replenish and which can be used for an initial burst of data. - /// * `bytes_complete_refill_time_ms` - number of milliseconds for the `TokenType::Bytes` - /// token bucket to go from zero Bytes to `bytes_total_capacity` Bytes. + /// * `bytes_one_time_burst` - initial extra credit on top of `bytes_total_capacity`, that does + /// not replenish and which can be used for an initial burst of data. + /// * `bytes_complete_refill_time_ms` - number of milliseconds for the `TokenType::Bytes` token + /// bucket to go from zero Bytes to `bytes_total_capacity` Bytes. /// * `ops_total_capacity` - the total capacity of the `TokenType::Ops` token bucket. - /// * `ops_one_time_burst` - initial extra credit on top of `ops_total_capacity`, - /// that does not replenish and which can be used for an initial burst of data. + /// * `ops_one_time_burst` - initial extra credit on top of `ops_total_capacity`, that does not + /// replenish and which can be used for an initial burst of data. /// * `ops_complete_refill_time_ms` - number of milliseconds for the `TokenType::Ops` token - /// bucket to go from zero Ops to `ops_total_capacity` Ops. + /// bucket to go from zero Ops to `ops_total_capacity` Ops. /// /// If either bytes/ops *size* or *refill_time* are **zero**, the limiter /// is **disabled** for that respective token type. @@ -794,7 +794,7 @@ pub(crate) mod tests { } // After a restore, we cannot be certain that the last_update field has the same value. - pub fn partial_eq(&self, other: &TokenBucket) -> bool { + pub(crate) fn partial_eq(&self, other: &TokenBucket) -> bool { (other.capacity() == self.capacity()) && (other.one_time_burst() == self.one_time_burst()) && (other.refill_time_ms() == self.refill_time_ms()) diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 0ad4df8aa19..0cde08a844d 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -1529,7 +1529,7 @@ mod tests { .as_cstring() .unwrap() .as_bytes_with_nul(), - [cmdline.as_bytes(), &[b'\0']].concat() + [cmdline.as_bytes(), b"\0"].concat() ); assert_ne!( boot_builder.kernel_file.metadata().unwrap().st_ino(), @@ -1554,7 +1554,7 @@ mod tests { .as_cstring() .unwrap() .as_bytes_with_nul(), - [cmdline.as_bytes(), &[b'\0']].concat() + [cmdline.as_bytes(), b"\0"].concat() ); assert_eq!( boot_source_builder.kernel_file.metadata().unwrap().st_ino(), diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 566228fd53a..b0c95529f46 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -249,7 +249,7 @@ pub struct PrebootApiController<'a> { } // TODO Remove when `EventManager` implements `std::fmt::Debug`. -impl<'a> fmt::Debug for PrebootApiController<'a> { +impl fmt::Debug for PrebootApiController<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PrebootApiController") .field("seccomp_filters", &self.seccomp_filters) @@ -572,20 +572,18 @@ impl<'a> PrebootApiController<'a> { load_params, self.vm_resources, ) - .map_err(|err| { + .inspect_err(|_| { // If restore fails, we consider the process is too dirty to recover. self.fatal_error = Some(BuildMicrovmFromRequestsError::Restore); - err })?; // Resume VM if load_params.resume_vm { vmm.lock() .expect("Poisoned lock") .resume_vm() - .map_err(|err| { + .inspect_err(|_| { // If resume fails, we consider the process is too dirty to recover. self.fatal_error = Some(BuildMicrovmFromRequestsError::Resume); - err })?; } // Set the VM diff --git a/src/vmm/src/vmm_config/boot_source.rs b/src/vmm/src/vmm_config/boot_source.rs index c40a0fde014..1bfed7bad9c 100644 --- a/src/vmm/src/vmm_config/boot_source.rs +++ b/src/vmm/src/vmm_config/boot_source.rs @@ -119,7 +119,7 @@ pub(crate) mod tests { assert!(boot_cfg.initrd_file.is_none()); assert_eq!( boot_cfg.cmdline.as_cstring().unwrap().as_bytes_with_nul(), - [DEFAULT_KERNEL_CMDLINE.as_bytes(), &[b'\0']].concat() + [DEFAULT_KERNEL_CMDLINE.as_bytes(), b"\0"].concat() ); } diff --git a/src/vmm/src/vmm_config/net.rs b/src/vmm/src/vmm_config/net.rs index 4b917c2ca48..8ece4e7e494 100644 --- a/src/vmm/src/vmm_config/net.rs +++ b/src/vmm/src/vmm_config/net.rs @@ -183,13 +183,9 @@ mod tests { use crate::rate_limiter::RateLimiter; impl NetBuilder { - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.net_devices.len() } - - pub fn is_empty(&self) -> bool { - self.net_devices.len() == 0 - } } fn create_netif(id: &str, name: &str, mac: &str) -> NetworkInterfaceConfig { diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index cb63afa4579..73779fbd928 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -759,7 +759,7 @@ pub enum VcpuEmulation { } #[cfg(test)] -pub mod tests { +pub(crate) mod tests { #![allow(clippy::undocumented_unsafe_blocks)] #[cfg(target_arch = "x86_64")] From e3088afaaa7276bf7c983e3b16223996a0c16f97 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 28 Nov 2024 10:57:39 +0000 Subject: [PATCH 083/464] chore(devtool): run cmd_build in privileged container This is needed for CI to install previous version of the toolchain used on the main branch. This change will need to be reverted after this PR is merged. Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- tools/devtool | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 36406c61bda..662c2583450 100755 --- a/tools/devtool +++ b/tools/devtool @@ -509,13 +509,17 @@ cmd_build() { # We don't need any special privileges for the build phase, so we run the # container as the current user/group. run_devctr \ - --user "$(id -u):$(id -g)" \ + --privileged \ --workdir "$workdir" \ ${extra_args} \ -- \ ./tools/release.sh --libc $libc --profile $profile ret=$? + # Running as root would have created some root-owned files under the build + # dir. Let's fix that. + cmd_fix_perms + if [ ! -z "$revision" ]; then popd git branch -D $branch_name From 85ebd24d8bea947c61e10a8d373e183f40fdb4ba Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 25 Nov 2024 13:56:41 +0000 Subject: [PATCH 084/464] docker: add what's needed for static seccomp analysis Add the rust-src component and the $(uname -m)-unknown-linux-musl targets for the nightly toolchain, and install python3-seccomp and rustfilt. Since the python bindings for libseccomp are not published to pip, we have to install it into the global python installation via apt-get, and then copy into our venv. Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index bebf1309e00..14867f3d9f1 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -76,6 +76,7 @@ RUN apt-get update \ tzdata \ tini \ squashfs-tools zstd \ + python3-seccomp \ # for aws-lc-rs cmake \ # for Qemu vhost-user-blk backend @@ -98,8 +99,13 @@ RUN cd /tmp/poetry \ ENV VIRTUAL_ENV=$VENV ENV PATH=$VENV/bin:$PATH +# apt-get installs it globally, to manually copy it into the venv +RUN cp /usr/lib/python3/dist-packages/seccomp.cpython-312-"$ARCH"-linux-gnu.so "$VENV"/lib/python3.12/site-packages/ + # Running the three as a single dockerfile command to avoid inflation of the image: -# - Install the Rust toolchain. Kani only work on x86, so only try to install it there +# - Install the Rust toolchain. +# - Kani always installs _some_ nightly toolchain, we reuse it for the seccomp filter analysis test. Dynamically +# determine the exact toolchain name, and install more components into it. # - Build and install crosvm (used as vhost-user-blk backend) # - Clean up cargo compilation directories # - Always install both x86_64 and aarch64 musl targets, as our rust-toolchain.toml would force on-the-fly installation of both anyway @@ -110,6 +116,10 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \ && cargo install --locked kani-verifier && cargo kani setup \ \ + && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ + && rustup component add rust-src --toolchain "$NIGHTLY_TOOLCHAIN" \ + && rustup target add "$ARCH"-unknown-linux-musl --toolchain "$NIGHTLY_TOOLCHAIN" \ + \ && apt-get update \ && apt-get -y install --no-install-recommends \ libcap-dev \ From de8076806d490abb8eb501a6606112da09b77317 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 25 Nov 2024 16:54:29 +0000 Subject: [PATCH 085/464] chore(devctr): add libseccomp to devctr Build static version of libseccomp with `musl-gcc`. This is needed for our musl builds as the version shipped in the ubuntu package is not compiled with `musl-gcc` and produces linker errors. Signed-off-by: Egor Lazarchuk Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 14867f3d9f1..153b34fc6ee 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -147,6 +147,22 @@ RUN cd /usr/include/$ARCH-linux-musl \ && ln -s ../linux linux \ && ln -s ../asm-generic asm-generic +# Install static version of libseccomp +# +RUN apt-get update \ + && apt-get -y install \ + libtool gperf \ + && git clone https://github.com/seccomp/libseccomp /tmp/libseccomp \ + && cd /tmp/libseccomp \ + && ./autogen.sh \ + && CC="musl-gcc -static" ./configure --enable-static=yes --enable-shared=false \ + && make install \ + && cd \ + && apt-get purge -y \ + libtool gperf \ + && apt-get autoremove -y \ + && rm -rf /tmp/libseccomp + # Build iperf3-vsock RUN mkdir "$TMP_BUILD_DIR" && cd "$TMP_BUILD_DIR" \ && git clone https://github.com/stefano-garzarella/iperf-vsock \ From 3592d48ce1733a15acccfe79555836f3002288d6 Mon Sep 17 00:00:00 2001 From: Jonathan Woollett-Light Date: Wed, 4 Oct 2023 11:30:33 +0100 Subject: [PATCH 086/464] build: Add `cargo-udeps` to devctr From: Jonathan Woollett-Light Adds `cargo-udeps` and the Rust `nightly` toolchain to support it, to dev container. Signed-off-by: Jonathan Woollett-Light Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 153b34fc6ee..9340c4c9c98 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -119,6 +119,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ && rustup component add rust-src --toolchain "$NIGHTLY_TOOLCHAIN" \ && rustup target add "$ARCH"-unknown-linux-musl --toolchain "$NIGHTLY_TOOLCHAIN" \ + && cargo +"$NIGHTLY_TOOLCHAIN" install cargo-udeps \ \ && apt-get update \ && apt-get -y install --no-install-recommends \ From ce95642296a7b638b91bbbfa7e5935206572d995 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 10:54:48 +0000 Subject: [PATCH 087/464] poetry: add fabric and netns dependencies These python dependencies are used for an upcoming PR about reusing SSH connection in our SSH tests. Signed-off-by: Patrick Roy --- tools/devctr/poetry.lock | 2123 +++++++++++++++++++++-------------- tools/devctr/pyproject.toml | 2 + 2 files changed, 1253 insertions(+), 872 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index 96f1d0c990a..eb969e9eda2 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -1,114 +1,99 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" -version = "2.4.0" +version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.0-py3-none-any.whl", hash = "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd"}, - {file = "aiohappyeyeballs-2.4.0.tar.gz", hash = "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2"}, + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, ] [[package]] name = "aiohttp" -version = "3.10.11" +version = "3.11.10" description = "Async http client/server framework (asyncio)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, - {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, - {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, - {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, - {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, - {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, - {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, - {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, - {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, - {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, - {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, - {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, - {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, - {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f"}, + {file = "aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df"}, + {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767"}, + {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d"}, + {file = "aiohttp-3.11.10-cp310-cp310-win32.whl", hash = "sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91"}, + {file = "aiohttp-3.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1"}, + {file = "aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0"}, + {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52"}, + {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"}, + {file = "aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4"}, + {file = "aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138"}, + {file = "aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b"}, + {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9"}, + {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc"}, + {file = "aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985"}, + {file = "aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf"}, + {file = "aiohttp-3.11.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99"}, + {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60"}, + {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836"}, + {file = "aiohttp-3.11.10-cp313-cp313-win32.whl", hash = "sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c"}, + {file = "aiohttp-3.11.10-cp313-cp313-win_amd64.whl", hash = "sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f"}, + {file = "aiohttp-3.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf"}, + {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1"}, + {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4"}, + {file = "aiohttp-3.11.10-cp39-cp39-win32.whl", hash = "sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be"}, + {file = "aiohttp-3.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74"}, + {file = "aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e"}, ] [package.dependencies] @@ -118,7 +103,8 @@ async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.12.0,<2.0" +propcache = ">=0.2.0" +yarl = ">=1.17.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] @@ -153,13 +139,13 @@ python-dateutil = ">=2.7.0" [[package]] name = "astroid" -version = "3.2.4" +version = "3.3.6" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, - {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, + {file = "astroid-3.3.6-py3-none-any.whl", hash = "sha256:db676dc4f3ae6bfe31cda227dc60e03438378d7a896aec57422c95634e8d722f"}, + {file = "astroid-3.3.6.tar.gz", hash = "sha256:6aaea045f938c735ead292204afdb977a36e989522b7833ef6fea94de743f442"}, ] [package.dependencies] @@ -167,31 +153,28 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "asttokens" -version = "2.4.1" +version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, - {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, + {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, + {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, ] -[package.dependencies] -six = ">=1.12.0" - [package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] +astroid = ["astroid (>=2,<4)"] +test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "async-timeout" -version = "4.0.3" +version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, ] [[package]] @@ -227,35 +210,73 @@ files = [ [package.dependencies] aiohttp = "*" +[[package]] +name = "bcrypt" +version = "4.2.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, + {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, + {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, + {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, + {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, + {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, + {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + [[package]] name = "black" -version = "24.8.0" +version = "24.10.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, - {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, - {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, - {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, - {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, - {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, - {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, - {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, - {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, - {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, - {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, - {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, - {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, - {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, - {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, - {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, - {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, - {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, - {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, - {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, - {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, - {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, ] [package.dependencies] @@ -269,7 +290,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -284,103 +305,197 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -408,6 +523,57 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "44.0.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "decorator" version = "5.1.1" @@ -419,15 +585,32 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deprecated" +version = "1.2.15" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] + [[package]] name = "dill" -version = "0.3.8" +version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" files = [ - {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, - {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, + {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, + {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, ] [package.extras] @@ -476,106 +659,141 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +[[package]] +name = "fabric" +version = "3.2.2" +description = "High level SSH command execution" +optional = false +python-versions = "*" +files = [ + {file = "fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"}, + {file = "fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"}, +] + +[package.dependencies] +decorator = ">=5" +deprecated = ">=1.2" +invoke = ">=2.0" +paramiko = ">=2.4" + +[package.extras] +pytest = ["pytest (>=7)"] + [[package]] name = "filelock" -version = "3.16.0" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"}, - {file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "frozenlist" -version = "1.4.1" +version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, + {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"}, + {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"}, + {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"}, + {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"}, + {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"}, + {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"}, + {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"}, + {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"}, + {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"}, + {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"}, + {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"}, + {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"}, + {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"}, + {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"}, + {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"}, + {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"}, + {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"}, + {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"}, + {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"}, + {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"}, + {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"}, + {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"}, + {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"}, + {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"}, + {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"}, + {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"}, + {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"}, + {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"}, + {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"}, + {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"}, + {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, ] [[package]] @@ -622,15 +840,18 @@ trusted-deps = ["arrow (==1.2.3)", "click (==8.1.3)", "sh (==1.14.3)"] [[package]] name = "idna" -version = "3.8" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -642,15 +863,26 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "invoke" +version = "2.2.0" +description = "Pythonic task execution" +optional = false +python-versions = ">=3.6" +files = [ + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, +] + [[package]] name = "ipython" -version = "8.27.0" +version = "8.30.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.27.0-py3-none-any.whl", hash = "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c"}, - {file = "ipython-8.27.0.tar.gz", hash = "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e"}, + {file = "ipython-8.30.0-py3-none-any.whl", hash = "sha256:85ec56a7e20f6c38fce7727dcca699ae4ffc85985aa7b23635a8008f918ae321"}, + {file = "ipython-8.30.0.tar.gz", hash = "sha256:cb0a405a306d2995a5cbb9901894d240784a9f341394c6ba3f4fe8c6eb89ff6e"}, ] [package.dependencies] @@ -660,16 +892,16 @@ exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} -prompt-toolkit = ">=3.0.41,<3.1.0" +prompt_toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" -stack-data = "*" +stack_data = "*" traitlets = ">=5.13.0" -typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing_extensions"] kernel = ["ipykernel"] matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] @@ -696,22 +928,22 @@ colors = ["colorama (>=0.4.6)"] [[package]] name = "jedi" -version = "0.19.1" +version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, - {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, + {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, + {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, ] [package.dependencies] -parso = ">=0.8.3,<0.9.0" +parso = ">=0.8.4,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] [[package]] name = "jsonschema" @@ -883,13 +1115,13 @@ files = [ [[package]] name = "mdformat" -version = "0.7.17" +version = "0.7.19" description = "CommonMark compliant Markdown formatter" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mdformat-0.7.17-py3-none-any.whl", hash = "sha256:91ffc5e203f5814a6ad17515c77767fd2737fc12ffd8b58b7bb1d8b9aa6effaa"}, - {file = "mdformat-0.7.17.tar.gz", hash = "sha256:a9dbb1838d43bb1e6f03bd5dca9412c552544a9bc42d6abb5dc32adfe8ae7c0d"}, + {file = "mdformat-0.7.19-py3-none-any.whl", hash = "sha256:5c360992adc118cf1479cbbe92bb3bd66dcd7f1a5a3a2ad6675915622c678cf1"}, + {file = "mdformat-0.7.19.tar.gz", hash = "sha256:a7d22df9802383432367864da907d2d147485b5cb6872e2d66937c1333e4d58a"}, ] [package.dependencies] @@ -937,13 +1169,13 @@ test = ["coverage", "pytest (>=7.3)", "pytest-cov"] [[package]] name = "mdformat-gfm" -version = "0.3.6" +version = "0.3.7" description = "Mdformat plugin for GitHub Flavored Markdown compatibility" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mdformat_gfm-0.3.6-py3-none-any.whl", hash = "sha256:579e3619bedd3b7123df888b6929ab8ac5dfc8205d0b67153b1633262bdafc42"}, - {file = "mdformat_gfm-0.3.6.tar.gz", hash = "sha256:b405ebf651a15c186ca06712100e33bbe72afeafb02aa4a4a28ea26cc3219678"}, + {file = "mdformat_gfm-0.3.7-py3-none-any.whl", hash = "sha256:c40966ef26e334226961ab77908dc9697ed63668f6383a18c80cca1cb4bb5c10"}, + {file = "mdformat_gfm-0.3.7.tar.gz", hash = "sha256:7deb2cd1d5334541af5454e52e116639796fc441ddc08e4415f967955950fe10"}, ] [package.dependencies] @@ -1115,66 +1347,78 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "netns" +version = "1.0" +description = "Wrapper for the Linux setns() system call" +optional = false +python-versions = "*" +files = [ + {file = "netns-1.0.tar.gz", hash = "sha256:dc994c53e415baa739072784292630724d609566fb4a60ed8feef38dd9ecdca5"}, +] + [[package]] name = "numpy" -version = "2.1.1" +version = "2.2.0" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" files = [ - {file = "numpy-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f"}, - {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7"}, - {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0"}, - {file = "numpy-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647"}, - {file = "numpy-2.1.1-cp310-cp310-win32.whl", hash = "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728"}, - {file = "numpy-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0"}, - {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca"}, - {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e"}, - {file = "numpy-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2"}, - {file = "numpy-2.1.1-cp311-cp311-win32.whl", hash = "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d"}, - {file = "numpy-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f"}, - {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"}, - {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a"}, - {file = "numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313"}, - {file = "numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed"}, - {file = "numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136"}, - {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb"}, - {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78"}, - {file = "numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556"}, - {file = "numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b"}, - {file = "numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f"}, - {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef"}, - {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c"}, - {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd"}, - {file = "numpy-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39"}, - {file = "numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e25507d85da11ff5066269d0bd25d06e0a0f2e908415534f3e603d2a78e4ffa"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a62eb442011776e4036af5c8b1a00b706c5bc02dc15eb5344b0c750428c94219"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:b606b1aaf802e6468c2608c65ff7ece53eae1a6874b3765f69b8ceb20c5fa78e"}, + {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:36b2b43146f646642b425dd2027730f99bac962618ec2052932157e213a040e9"}, + {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fe8f3583e0607ad4e43a954e35c1748b553bfe9fdac8635c02058023277d1b3"}, + {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:122fd2fcfafdefc889c64ad99c228d5a1f9692c3a83f56c292618a59aa60ae83"}, + {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f2f5cddeaa4424a0a118924b988746db6ffa8565e5829b1841a8a3bd73eb59a"}, + {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fe4bb0695fe986a9e4deec3b6857003b4cfe5c5e4aac0b95f6a658c14635e31"}, + {file = "numpy-2.2.0-cp310-cp310-win32.whl", hash = "sha256:b30042fe92dbd79f1ba7f6898fada10bdaad1847c44f2dff9a16147e00a93661"}, + {file = "numpy-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dc1d6d66f8d37843ed281773c7174f03bf7ad826523f73435deb88ba60d2d4"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9874bc2ff574c40ab7a5cbb7464bf9b045d617e36754a7bc93f933d52bd9ffc6"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0da8495970f6b101ddd0c38ace92edea30e7e12b9a926b57f5fabb1ecc25bb90"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0557eebc699c1c34cccdd8c3778c9294e8196df27d713706895edc6f57d29608"}, + {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:3579eaeb5e07f3ded59298ce22b65f877a86ba8e9fe701f5576c99bb17c283da"}, + {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40deb10198bbaa531509aad0cd2f9fadb26c8b94070831e2208e7df543562b74"}, + {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2aed8fcf8abc3020d6a9ccb31dbc9e7d7819c56a348cc88fd44be269b37427e"}, + {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a222d764352c773aa5ebde02dd84dba3279c81c6db2e482d62a3fa54e5ece69b"}, + {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4e58666988605e251d42c2818c7d3d8991555381be26399303053b58a5bbf30d"}, + {file = "numpy-2.2.0-cp311-cp311-win32.whl", hash = "sha256:4723a50e1523e1de4fccd1b9a6dcea750c2102461e9a02b2ac55ffeae09a4410"}, + {file = "numpy-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:16757cf28621e43e252c560d25b15f18a2f11da94fea344bf26c599b9cf54b73"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67"}, + {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e"}, + {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038"}, + {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03"}, + {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a"}, + {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef"}, + {file = "numpy-2.2.0-cp312-cp312-win32.whl", hash = "sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1"}, + {file = "numpy-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69"}, + {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13"}, + {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671"}, + {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571"}, + {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d"}, + {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742"}, + {file = "numpy-2.2.0-cp313-cp313-win32.whl", hash = "sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e"}, + {file = "numpy-2.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca"}, + {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d"}, + {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529"}, + {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3"}, + {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab"}, + {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72"}, + {file = "numpy-2.2.0-cp313-cp313t-win32.whl", hash = "sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066"}, + {file = "numpy-2.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e12c6c1ce84628c52d6367863773f7c8c8241be554e8b79686e91a43f1733773"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:b6207dc8fb3c8cb5668e885cef9ec7f70189bec4e276f0ff70d5aa078d32c88e"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a50aeff71d0f97b6450d33940c7181b08be1441c6c193e678211bff11aa725e7"}, + {file = "numpy-2.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:df12a1f99b99f569a7c2ae59aa2d31724e8d835fc7f33e14f4792e3071d11221"}, + {file = "numpy-2.2.0.tar.gz", hash = "sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0"}, ] [[package]] @@ -1212,15 +1456,36 @@ openapi-schema-validator = ">=0.6.0,<0.7.0" [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] +[[package]] +name = "paramiko" +version = "3.5.0" +description = "SSH2 protocol library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, + {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, +] + +[package.dependencies] +bcrypt = ">=3.2" +cryptography = ">=3.3" +pynacl = ">=1.5" + +[package.extras] +all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +invoke = ["invoke (>=2.0)"] + [[package]] name = "parso" version = "0.8.4" @@ -1274,13 +1539,13 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.3.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, - {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] @@ -1305,13 +1570,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.47" +version = "3.0.48" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, - {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, + {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, + {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, ] [package.dependencies] @@ -1319,139 +1584,124 @@ wcwidth = "*" [[package]] name = "propcache" -version = "0.2.0" +version = "0.2.1" description = "Accelerated property cache" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, - {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, - {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, - {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, - {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, - {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, - {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, - {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, - {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, - {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, - {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, - {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, - {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, - {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, - {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, + {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, + {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, + {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, + {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, + {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, + {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, + {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, + {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, + {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, + {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, + {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, + {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, ] [[package]] name = "psutil" -version = "6.0.0" +version = "6.1.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, - {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, - {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, - {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, - {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, - {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, - {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, - {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, - {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, - {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, - {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, - {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, - {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, + {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, + {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, + {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, + {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, + {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, + {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, + {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, + {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, ] [package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] +test = ["pytest", "pytest-xdist", "setuptools"] [[package]] name = "ptyprocess" @@ -1478,6 +1728,17 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pygments" version = "2.18.0" @@ -1494,17 +1755,17 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "3.2.7" +version = "3.3.2" description = "python code static checker" optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, - {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, + {file = "pylint-3.3.2-py3-none-any.whl", hash = "sha256:77f068c287d49b8683cd7c6e624243c74f92890f767f106ffa1ddf3c0a54cb7a"}, + {file = "pylint-3.3.2.tar.gz", hash = "sha256:9ec054ec992cd05ad30a6df1676229739a73f8feeabf3912c995d17601052b01"}, ] [package.dependencies] -astroid = ">=3.2.4,<=3.3.0-dev0" +astroid = ">=3.3.5,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -1521,15 +1782,41 @@ tomlkit = ">=0.10.1" spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] +[[package]] +name = "pynacl" +version = "1.5.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[package.dependencies] +cffi = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] + [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -1767,114 +2054,114 @@ six = "*" [[package]] name = "rpds-py" -version = "0.20.0" +version = "0.22.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, - {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, - {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, - {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, - {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, - {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, - {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, - {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, - {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, - {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, - {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, - {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, - {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, - {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, - {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, + {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, + {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, + {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, + {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, + {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, + {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, + {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, + {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, + {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, + {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, + {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, ] [[package]] @@ -1897,61 +2184,52 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] name = "ruamel-yaml-clib" -version = "0.2.8" +version = "0.2.12" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, - {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, - {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, + {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, ] [[package]] @@ -2006,99 +2284,96 @@ test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.3 [[package]] name = "setproctitle" -version = "1.3.3" +version = "1.3.4" description = "A Python module to customize the process title" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:897a73208da48db41e687225f355ce993167079eda1260ba5e13c4e53be7f754"}, - {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c331e91a14ba4076f88c29c777ad6b58639530ed5b24b5564b5ed2fd7a95452"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbbd6c7de0771c84b4aa30e70b409565eb1fc13627a723ca6be774ed6b9d9fa3"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c05ac48ef16ee013b8a326c63e4610e2430dbec037ec5c5b58fcced550382b74"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1342f4fdb37f89d3e3c1c0a59d6ddbedbde838fff5c51178a7982993d238fe4f"}, - {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc74e84fdfa96821580fb5e9c0b0777c1c4779434ce16d3d62a9c4d8c710df39"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9617b676b95adb412bb69645d5b077d664b6882bb0d37bfdafbbb1b999568d85"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6a249415f5bb88b5e9e8c4db47f609e0bf0e20a75e8d744ea787f3092ba1f2d0"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:38da436a0aaace9add67b999eb6abe4b84397edf4a78ec28f264e5b4c9d53cd5"}, - {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:da0d57edd4c95bf221b2ebbaa061e65b1788f1544977288bdf95831b6e44e44d"}, - {file = "setproctitle-1.3.3-cp310-cp310-win32.whl", hash = "sha256:a1fcac43918b836ace25f69b1dca8c9395253ad8152b625064415b1d2f9be4fb"}, - {file = "setproctitle-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:200620c3b15388d7f3f97e0ae26599c0c378fdf07ae9ac5a13616e933cbd2086"}, - {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:334f7ed39895d692f753a443102dd5fed180c571eb6a48b2a5b7f5b3564908c8"}, - {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:950f6476d56ff7817a8fed4ab207727fc5260af83481b2a4b125f32844df513a"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:195c961f54a09eb2acabbfc90c413955cf16c6e2f8caa2adbf2237d1019c7dd8"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f05e66746bf9fe6a3397ec246fe481096664a9c97eb3fea6004735a4daf867fd"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5901a31012a40ec913265b64e48c2a4059278d9f4e6be628441482dd13fb8b5"}, - {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64286f8a995f2cd934082b398fc63fca7d5ffe31f0e27e75b3ca6b4efda4e353"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:184239903bbc6b813b1a8fc86394dc6ca7d20e2ebe6f69f716bec301e4b0199d"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:664698ae0013f986118064b6676d7dcd28fefd0d7d5a5ae9497cbc10cba48fa5"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e5119a211c2e98ff18b9908ba62a3bd0e3fabb02a29277a7232a6fb4b2560aa0"}, - {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:417de6b2e214e837827067048f61841f5d7fc27926f2e43954567094051aff18"}, - {file = "setproctitle-1.3.3-cp311-cp311-win32.whl", hash = "sha256:6a143b31d758296dc2f440175f6c8e0b5301ced3b0f477b84ca43cdcf7f2f476"}, - {file = "setproctitle-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a680d62c399fa4b44899094027ec9a1bdaf6f31c650e44183b50d4c4d0ccc085"}, - {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d4460795a8a7a391e3567b902ec5bdf6c60a47d791c3b1d27080fc203d11c9dc"}, - {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bdfd7254745bb737ca1384dee57e6523651892f0ea2a7344490e9caefcc35e64"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477d3da48e216d7fc04bddab67b0dcde633e19f484a146fd2a34bb0e9dbb4a1e"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab2900d111e93aff5df9fddc64cf51ca4ef2c9f98702ce26524f1acc5a786ae7"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:088b9efc62d5aa5d6edf6cba1cf0c81f4488b5ce1c0342a8b67ae39d64001120"}, - {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6d50252377db62d6a0bb82cc898089916457f2db2041e1d03ce7fadd4a07381"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:87e668f9561fd3a457ba189edfc9e37709261287b52293c115ae3487a24b92f6"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:287490eb90e7a0ddd22e74c89a92cc922389daa95babc833c08cf80c84c4df0a"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe1c49486109f72d502f8be569972e27f385fe632bd8895f4730df3c87d5ac8"}, - {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a6ba2494a6449b1f477bd3e67935c2b7b0274f2f6dcd0f7c6aceae10c6c6ba3"}, - {file = "setproctitle-1.3.3-cp312-cp312-win32.whl", hash = "sha256:2df2b67e4b1d7498632e18c56722851ba4db5d6a0c91aaf0fd395111e51cdcf4"}, - {file = "setproctitle-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:f38d48abc121263f3b62943f84cbaede05749047e428409c2c199664feb6abc7"}, - {file = "setproctitle-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:816330675e3504ae4d9a2185c46b573105d2310c20b19ea2b4596a9460a4f674"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f960bc22d8d8e4ac886d1e2e21ccbd283adcf3c43136161c1ba0fa509088e0"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e6e7adff74796ef12753ff399491b8827f84f6c77659d71bd0b35870a17d8f"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53bc0d2358507596c22b02db079618451f3bd720755d88e3cccd840bafb4c41c"}, - {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6d20f9541f5f6ac63df553b6d7a04f313947f550eab6a61aa758b45f0d5657"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c1c84beab776b0becaa368254801e57692ed749d935469ac10e2b9b825dbdd8e"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:507e8dc2891021350eaea40a44ddd887c9f006e6b599af8d64a505c0f718f170"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b1067647ac7aba0b44b591936118a22847bda3c507b0a42d74272256a7a798e9"}, - {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2e71f6365744bf53714e8bd2522b3c9c1d83f52ffa6324bd7cbb4da707312cd8"}, - {file = "setproctitle-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:7f1d36a1e15a46e8ede4e953abb104fdbc0845a266ec0e99cc0492a4364f8c44"}, - {file = "setproctitle-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9a402881ec269d0cc9c354b149fc29f9ec1a1939a777f1c858cdb09c7a261df"}, - {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ff814dea1e5c492a4980e3e7d094286077054e7ea116cbeda138819db194b2cd"}, - {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:accb66d7b3ccb00d5cd11d8c6e07055a4568a24c95cf86109894dcc0c134cc89"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554eae5a5b28f02705b83a230e9d163d645c9a08914c0ad921df363a07cf39b1"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a911b26264dbe9e8066c7531c0591cfab27b464459c74385b276fe487ca91c12"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2982efe7640c4835f7355fdb4da313ad37fb3b40f5c69069912f8048f77b28c8"}, - {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3f4274b80709d8bcab2f9a862973d453b308b97a0b423a501bcd93582852e3"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:af2c67ae4c795d1674a8d3ac1988676fa306bcfa1e23fddb5e0bd5f5635309ca"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:af4061f67fd7ec01624c5e3c21f6b7af2ef0e6bab7fbb43f209e6506c9ce0092"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:37a62cbe16d4c6294e84670b59cf7adcc73faafe6af07f8cb9adaf1f0e775b19"}, - {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a83ca086fbb017f0d87f240a8f9bbcf0809f3b754ee01cec928fff926542c450"}, - {file = "setproctitle-1.3.3-cp38-cp38-win32.whl", hash = "sha256:059f4ce86f8cc92e5860abfc43a1dceb21137b26a02373618d88f6b4b86ba9b2"}, - {file = "setproctitle-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ab92e51cd4a218208efee4c6d37db7368fdf182f6e7ff148fb295ecddf264287"}, - {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c7951820b77abe03d88b114b998867c0f99da03859e5ab2623d94690848d3e45"}, - {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc94cf128676e8fac6503b37763adb378e2b6be1249d207630f83fc325d9b11"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f5d9027eeda64d353cf21a3ceb74bb1760bd534526c9214e19f052424b37e42"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e4a8104db15d3462e29d9946f26bed817a5b1d7a47eabca2d9dc2b995991503"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32c41ace41f344d317399efff4cffb133e709cec2ef09c99e7a13e9f3b9483c"}, - {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbf16381c7bf7f963b58fb4daaa65684e10966ee14d26f5cc90f07049bfd8c1e"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e18b7bd0898398cc97ce2dfc83bb192a13a087ef6b2d5a8a36460311cb09e775"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69d565d20efe527bd8a9b92e7f299ae5e73b6c0470f3719bd66f3cd821e0d5bd"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ddedd300cd690a3b06e7eac90ed4452348b1348635777ce23d460d913b5b63c3"}, - {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:415bfcfd01d1fbf5cbd75004599ef167a533395955305f42220a585f64036081"}, - {file = "setproctitle-1.3.3-cp39-cp39-win32.whl", hash = "sha256:21112fcd2195d48f25760f0eafa7a76510871bbb3b750219310cf88b04456ae3"}, - {file = "setproctitle-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:5a740f05d0968a5a17da3d676ce6afefebeeeb5ce137510901bf6306ba8ee002"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6b9e62ddb3db4b5205c0321dd69a406d8af9ee1693529d144e86bd43bcb4b6c0"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e3b99b338598de0bd6b2643bf8c343cf5ff70db3627af3ca427a5e1a1a90dd9"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ae9a02766dad331deb06855fb7a6ca15daea333b3967e214de12cfae8f0ef5"}, - {file = "setproctitle-1.3.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:200ede6fd11233085ba9b764eb055a2a191fb4ffb950c68675ac53c874c22e20"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d3a953c50776751e80fe755a380a64cb14d61e8762bd43041ab3f8cc436092f"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e08e232b78ba3ac6bc0d23ce9e2bee8fad2be391b7e2da834fc9a45129eb87"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1da82c3e11284da4fcbf54957dafbf0655d2389cd3d54e4eaba636faf6d117a"}, - {file = "setproctitle-1.3.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:aeaa71fb9568ebe9b911ddb490c644fbd2006e8c940f21cb9a1e9425bd709574"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:59335d000c6250c35989394661eb6287187854e94ac79ea22315469ee4f4c244"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3ba57029c9c50ecaf0c92bb127224cc2ea9fda057b5d99d3f348c9ec2855ad3"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d876d355c53d975c2ef9c4f2487c8f83dad6aeaaee1b6571453cb0ee992f55f6"}, - {file = "setproctitle-1.3.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:224602f0939e6fb9d5dd881be1229d485f3257b540f8a900d4271a2c2aa4e5f4"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d7f27e0268af2d7503386e0e6be87fb9b6657afd96f5726b733837121146750d"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5e7266498cd31a4572378c61920af9f6b4676a73c299fce8ba93afd694f8ae7"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33c5609ad51cd99d388e55651b19148ea99727516132fb44680e1f28dd0d1de9"}, - {file = "setproctitle-1.3.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:eae8988e78192fd1a3245a6f4f382390b61bce6cfcc93f3809726e4c885fa68d"}, - {file = "setproctitle-1.3.3.tar.gz", hash = "sha256:c913e151e7ea01567837ff037a23ca8740192880198b7fbb90b16d181607caae"}, + {file = "setproctitle-1.3.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0f6661a69c68349172ba7b4d5dd65fec2b0917abc99002425ad78c3e58cf7595"}, + {file = "setproctitle-1.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:754bac5e470adac7f7ec2239c485cd0b75f8197ca8a5b86ffb20eb3a3676cc42"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7bc7088c15150745baf66db62a4ced4507d44419eb66207b609f91b64a682af"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a46ef3ecf61e4840fbc1145fdd38acf158d0da7543eda7b773ed2b30f75c2830"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcb09d5c0ffa043254ec9a734a73f3791fec8bf6333592f906bb2e91ed2af1a"}, + {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06c16b7a91cdc5d700271899e4383384a61aae83a3d53d0e2e5a266376083342"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9f9732e59863eaeedd3feef94b2b216cb86d40dda4fad2d0f0aaec3b31592716"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e152f4ab9ea1632b5fecdd87cee354f2b2eb6e2dfc3aceb0eb36a01c1e12f94c"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:020ea47a79b2bbd7bd7b94b85ca956ba7cb026e82f41b20d2e1dac4008cead25"}, + {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c52b12b10e4057fc302bd09cb3e3f28bb382c30c044eb3396e805179a8260e4"}, + {file = "setproctitle-1.3.4-cp310-cp310-win32.whl", hash = "sha256:a65a147f545f3fac86f11acb2d0b316d3e78139a9372317b7eb50561b2817ba0"}, + {file = "setproctitle-1.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:66821fada6426998762a3650a37fba77e814a249a95b1183011070744aff47f6"}, + {file = "setproctitle-1.3.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0f749f07002c2d6fecf37cedc43207a88e6c651926a470a5f229070cf791879"}, + {file = "setproctitle-1.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90ea8d302a5d30b948451d146e94674a3c5b020cc0ced9a1c28f8ddb0f203a5d"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f859c88193ed466bee4eb9d45fbc29d2253e6aa3ccd9119c9a1d8d95f409a60d"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3afa5a0ed08a477ded239c05db14c19af585975194a00adf594d48533b23701"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a78fce9018cc3e9a772b6537bbe3fe92380acf656c9f86db2f45e685af376e"}, + {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d758e2eed2643afac5f2881542fbb5aa97640b54be20d0a5ed0691d02f0867d"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ef133a1a2ee378d549048a12d56f4ef0e2b9113b0b25b6b77821e9af94d50634"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d2a154b79d5fb42d1eff06e05e22f0e8091261d877dd47b37d31352b74ecc37"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:202eae632815571297833876a0f407d0d9c7ad9d843b38adbe687fe68c5192ee"}, + {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2b0080819859e80a7776ac47cf6accb4b7ad313baf55fabac89c000480dcd103"}, + {file = "setproctitle-1.3.4-cp311-cp311-win32.whl", hash = "sha256:9c9d7d1267dee8c6627963d9376efa068858cfc8f573c083b1b6a2d297a8710f"}, + {file = "setproctitle-1.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:475986ddf6df65d619acd52188336a20f616589403f5a5ceb3fc70cdc137037a"}, + {file = "setproctitle-1.3.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d06990dcfcd41bb3543c18dd25c8476fbfe1f236757f42fef560f6aa03ac8dfc"}, + {file = "setproctitle-1.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:317218c9d8b17a010ab2d2f0851e8ef584077a38b1ba2b7c55c9e44e79a61e73"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5fefb53b9d9f334a5d9ec518a36b92a10b936011ac8a6b6dffd60135f16459"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0855006261635e8669646c7c304b494b6df0a194d2626683520103153ad63cc9"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a88e466fcaee659679c1d64dcb2eddbcb4bfadffeb68ba834d9c173a25b6184"}, + {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f963b6ed8ba33eda374a98d979e8a0eaf21f891b6e334701693a2c9510613c4c"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:122c2e05697fa91f5d23f00bbe98a9da1bd457b32529192e934095fadb0853f1"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1bba0a866f5895d5b769d8c36b161271c7fd407e5065862ab80ff91c29fbe554"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97f1f861998e326e640708488c442519ad69046374b2c3fe9bcc9869b387f23c"}, + {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:726aee40357d4bdb70115442cb85ccc8e8bc554fc0bbbaa3a57cbe81df42287d"}, + {file = "setproctitle-1.3.4-cp312-cp312-win32.whl", hash = "sha256:04d6ba8b816dbb0bfd62000b0c3e583160893e6e8c4233e1dca1a9ae4d95d924"}, + {file = "setproctitle-1.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:9c76e43cb351ba8887371240b599925cdf3ecececc5dfb7125c71678e7722c55"}, + {file = "setproctitle-1.3.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6e3b177e634aa6bbbfbf66d097b6d1cdb80fc60e912c7d8bace2e45699c07dd"}, + {file = "setproctitle-1.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6b17655a5f245b416e127e02087ea6347a48821cc4626bc0fd57101bfcd88afc"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa5057a86df920faab8ee83960b724bace01a3231eb8e3f2c93d78283504d598"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149fdfb8a26a555780c4ce53c92e6d3c990ef7b30f90a675eca02e83c6d5f76d"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ded03546938a987f463c68ab98d683af87a83db7ac8093bbc179e77680be5ba2"}, + {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ab9f5b7f2bbc1754bc6292d9a7312071058e5a891b0391e6d13b226133f36aa"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0b19813c852566fa031902124336fa1f080c51e262fc90266a8c3d65ca47b74c"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db78b645dc63c0ccffca367a498f3b13492fb106a2243a1e998303ba79c996e2"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b669aaac70bd9f03c070270b953f78d9ee56c4af6f0ff9f9cd3e6d1878c10b40"}, + {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6dc3d656702791565994e64035a208be56b065675a5bc87b644c657d6d9e2232"}, + {file = "setproctitle-1.3.4-cp313-cp313-win32.whl", hash = "sha256:091f682809a4d12291cf0205517619d2e7014986b7b00ebecfde3d76f8ae5a8f"}, + {file = "setproctitle-1.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:adcd6ba863a315702184d92d3d3bbff290514f24a14695d310f02ae5e28bd1f7"}, + {file = "setproctitle-1.3.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:acf41cf91bbc5a36d1fa4455a818bb02bf2a4ccfed2f892ba166ba2fcbb0ec8a"}, + {file = "setproctitle-1.3.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ceb3ce3262b0e8e088e4117175591b7a82b3bdc5e52e33b1e74778b5fb53fd38"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2ef636a6a25fe7f3d5a064bea0116b74a4c8c7df9646b17dc7386c439a26cf"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28b8614de08679ae95bc4e8d6daaef6b61afdf027fa0d23bf13d619000286b3c"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24f3c8be826a7d44181eac2269b15b748b76d98cd9a539d4c69f09321dcb5c12"}, + {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9d79b1bf833af63b7c720a6604eb16453ac1ad4e718eb8b59d1f97d986b98c"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fb693000b65842c85356b667d057ae0d0bac6519feca7e1c437cc2cfeb0afc59"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a166251b8fbc6f2755e2ce9d3c11e9edb0c0c7d2ed723658ff0161fbce26ac1c"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:0361428e6378911a378841509c56ba472d991cbed1a7e3078ec0cacc103da44a"}, + {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:62d66e0423e3bd520b4c897063506b309843a8d07343fbfad04197e91a4edd28"}, + {file = "setproctitle-1.3.4-cp38-cp38-win32.whl", hash = "sha256:5edd01909348f3b0b2da329836d6b5419cd4869fec2e118e8ff3275b38af6267"}, + {file = "setproctitle-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:59e0dda9ad245921af0328035a961767026e1fa94bb65957ab0db0a0491325d6"}, + {file = "setproctitle-1.3.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bdaaa81a6e95a0a19fba0285f10577377f3503ae4e9988b403feba79da3e2f80"}, + {file = "setproctitle-1.3.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ee5b19a2d794463bcc19153dfceede7beec784b4cf7967dec0bc0fc212ab3a3"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3058a1bb0c767b3a6ccbb38b27ef870af819923eb732e21e44a3f300370fe159"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a97d37ee4fe0d1c6e87d2a97229c27a88787a8f4ebfbdeee95f91b818e52efe"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e61dd7d05da11fc69bb86d51f1e0ee08f74dccf3ecf884c94de41135ffdc75d"}, + {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb115d53dc2a1299ae72f1119c96a556db36073bacb6da40c47ece5db0d9587"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:342570716e2647a51ea859b8a9126da9dc1a96a0153c9c0a3514effd60ab57ad"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ad212ae2b03951367a69584af034579b34e1e4199a75d377ef9f8e08ee299b1"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4afcb38e22122465013f4621b7e9ff8d42a7a48ae0ffeb94133a806cb91b4aad"}, + {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:30bb223e6c3f95ad9e9bb2a113292759e947d1cfd60dbd4adb55851c370006b2"}, + {file = "setproctitle-1.3.4-cp39-cp39-win32.whl", hash = "sha256:5f0521ed3bb9f02e9486573ea95e2062cd6bf036fa44e640bd54a06f22d85f35"}, + {file = "setproctitle-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:0baadeb27f9e97e65922b4151f818b19c311d30b9efdb62af0e53b3db4006ce2"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:939d364a187b2adfbf6ae488664277e717d56c7951a4ddeb4f23b281bc50bfe5"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb8a6a19be0cbf6da6fcbf3698b76c8af03fe83e4bd77c96c3922be3b88bf7da"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779006f9e1aade9522a40e8d9635115ab15dd82b7af8e655967162e9c01e2573"}, + {file = "setproctitle-1.3.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5519f2a7b8c535b0f1f77b30441476571373add72008230c81211ee17b423b57"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:743836d484151334ebba1490d6907ca9e718fe815dcd5756f2a01bc3067d099c"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abda20aff8d1751e48d7967fa8945fef38536b82366c49be39b83678d4be3893"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a2041b5788ce52f218b5be94af458e04470f997ab46fdebd57cf0b8374cc20e"}, + {file = "setproctitle-1.3.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2c3b1ce68746557aa6e6f4547e76883925cdc7f8d7c7a9f518acd203f1265ca5"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0b6a4cbabf024cb263a45bdef425760f14470247ff223f0ec51699ca9046c0fe"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e55d7ecc68bdc80de5a553691a3ed260395d5362c19a266cf83cbb4e046551f"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02ca3802902d91a89957f79da3ec44b25b5804c88026362cb85eea7c1fbdefd1"}, + {file = "setproctitle-1.3.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:47669fc8ed8b27baa2d698104732234b5389f6a59c37c046f6bcbf9150f7a94e"}, + {file = "setproctitle-1.3.4.tar.gz", hash = "sha256:3b40d32a3e1f04e94231ed6dfee0da9e43b4f9c6b5450d53e6dd7754c34e0c50"}, ] [package.extras] @@ -2116,24 +2391,24 @@ files = [ [[package]] name = "sh" -version = "2.0.7" +version = "2.1.0" description = "Python subprocess replacement" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "sh-2.0.7-py3-none-any.whl", hash = "sha256:2f2f79a65abd00696cf2e9ad26508cf8abb6dba5745f40255f1c0ded2876926d"}, - {file = "sh-2.0.7.tar.gz", hash = "sha256:029d45198902bfb967391eccfd13a88d92f7cebd200411e93f99ebacc6afbb35"}, + {file = "sh-2.1.0-py3-none-any.whl", hash = "sha256:bf5e44178dd96a542126c2774e9b7ab1d89bfe0e2ef84d92e6d0ed7358d63d01"}, + {file = "sh-2.1.0.tar.gz", hash = "sha256:7e27301c574bec8ca5bf6f211851357526455ee97cd27a7c4c6cc5e2375399cb"}, ] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -2172,13 +2447,43 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] @@ -2260,95 +2565,169 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] +[[package]] +name = "wrapt" +version = "1.17.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +files = [ + {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, + {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, + {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, + {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, + {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, + {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, + {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, + {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, + {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, + {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, + {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, + {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, + {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, + {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, + {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, + {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, + {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, + {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, + {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, + {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, + {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, + {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, + {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, +] + [[package]] name = "yarl" -version = "1.17.2" +version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" files = [ - {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"}, - {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"}, - {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"}, - {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"}, - {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"}, - {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"}, - {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"}, - {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"}, - {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"}, - {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"}, - {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"}, - {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"}, - {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"}, - {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"}, - {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"}, - {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"}, - {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"}, - {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"}, - {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"}, - {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"}, - {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"}, - {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"}, - {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"}, - {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"}, - {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"}, - {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"}, - {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"}, - {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"}, - {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, + {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, + {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, + {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, + {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, + {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, + {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, + {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, + {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, + {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, + {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, + {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, + {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, ] [package.dependencies] @@ -2359,4 +2738,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "e38bfcb8811fb9b774956ed4b0e82603dbe5b66d8cb5bc4af6ed86417a9d5d1d" +content-hash = "c3b6e2c1d9a0a7926b61ca38f9e91fd1c1c0519a1703d6eaa0fd07fcf5898cbd" diff --git a/tools/devctr/pyproject.toml b/tools/devctr/pyproject.toml index a4f7178aa5d..188a3b315bd 100644 --- a/tools/devctr/pyproject.toml +++ b/tools/devctr/pyproject.toml @@ -10,6 +10,7 @@ aws-embedded-metrics = "^3.1.0" black = "^24.3.0" # Gitlint locks this to 8.1.3. Lock from our side too to prevent different versions click = "8.1.3" +fabric = "^3.2.2" filelock = "^3.13.4" gitlint = "^0.19.1" ipython = "^8.15.0" @@ -18,6 +19,7 @@ mdformat = "^0.7.17" mdformat-gfm = "^0.3.5" mdformat-footnote = "^0.1.1" mdformat-frontmatter = "^2.0.8" +netns = "^1.0.0" openapi-spec-validator = "^0.7.1" psutil = "^6.0.0" pylint = "^3" From 36937ed30797a931fab133e3f63ec6eda4450a03 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 9 Dec 2024 17:38:01 +0000 Subject: [PATCH 088/464] chore: bump devctr version accumulate all the dockerfile changes into a new devctr version Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 662c2583450..3b4d89ec392 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:-v75} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v76} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. From 48be9c9a58b2dcca2888a0386db4e035516ef2ae Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:01:49 +0000 Subject: [PATCH 089/464] chore: update kvm-ioctls This is needed to work around a bug in `VmFd::create_device`, where undefined behavior caused a miscompilation on newer rust toolchains. Signed-off-by: Patrick Roy --- Cargo.lock | 6 +++--- src/vmm/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f31b84f68c9..28561608a6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "acpi_tables" @@ -832,9 +832,9 @@ dependencies = [ [[package]] name = "kvm-ioctls" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "337d1afa126368bbd6a5c328048f71a69a737e9afe7e436b392a8f8d770c9171" +checksum = "e013ae7fcd2c6a8f384104d16afe7ea02969301ea2bb2a56e44b011ebc907cab" dependencies = [ "bitflags 2.6.0", "kvm-bindings", diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 31acb7362a8..ec3137be748 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -23,7 +23,7 @@ event-manager = "0.4.0" gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } -kvm-ioctls = "0.19.0" +kvm-ioctls = "0.19.1" lazy_static = "1.5.0" libc = "0.2.168" linux-loader = "0.13.0" From de0d42e8192316e9552621db684dbecd96068284 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:13:09 +0000 Subject: [PATCH 090/464] chore: suppress new pylint lint With the devctr's python dependencies update, we pulled in a new pylint version, which has a new `too-many-positional-arguments` lint. Fixing this would be a significant refactor, so just suppress it, as it seems low-value. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/style/test_python.py b/tests/integration_tests/style/test_python.py index 6a836dc4287..b04b93dace2 100644 --- a/tests/integration_tests/style/test_python.py +++ b/tests/integration_tests/style/test_python.py @@ -37,7 +37,7 @@ def test_python_pylint(): "fixme,too-many-instance-attributes,import-error," "too-many-locals,too-many-arguments,consider-using-f-string," "consider-using-with,implicit-str-concat,line-too-long,redefined-outer-name," - "broad-exception-raised,duplicate-code tests tools .buildkite/*.py" + "broad-exception-raised,duplicate-code,too-many-positional-arguments tests tools .buildkite/*.py" ) run( linter_cmd, From f735be33f667f35911f5410fe89318f45dd72387 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 11:40:22 +0000 Subject: [PATCH 091/464] fix: do not double close file descriptors in unittests With newer rust toolchains, rust will SIGABRT if an already closed file descriptor is closed in the the `Drop` implementation for `File`. This also applies to creating `File`s with invalid file descriptors. Thus fix tests that accidentally double-close fds, and remove those that explicitly construct `File`s with invalid file descriptors (they are redundant now anyway, because Rust would abort if this ever happened). Signed-off-by: Patrick Roy --- .../arch/aarch64/gic/gicv2/regs/dist_regs.rs | 3 ++ .../arch/aarch64/gic/gicv2/regs/icc_regs.rs | 3 ++ src/vmm/src/arch/aarch64/gic/gicv3/mod.rs | 3 ++ .../arch/aarch64/gic/gicv3/regs/dist_regs.rs | 3 ++ .../arch/aarch64/gic/gicv3/regs/icc_regs.rs | 3 ++ .../aarch64/gic/gicv3/regs/redist_regs.rs | 3 ++ src/vmm/src/arch/aarch64/vcpu.rs | 3 ++ .../src/devices/virtio/block/virtio/io/mod.rs | 29 ------------------- src/vmm/src/devices/virtio/net/device.rs | 6 ++++ src/vmm/src/devices/virtio/net/tap.rs | 13 --------- src/vmm/src/vstate/vcpu/aarch64.rs | 6 ++++ src/vmm/src/vstate/vcpu/x86_64.rs | 4 +-- 12 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs index 3ec73490038..a4179e895ae 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs @@ -162,5 +162,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 1)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs index aea6cb722b6..be963a8327e 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs @@ -120,5 +120,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 2)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs index 21f9b94218d..50d2e5130db 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs @@ -220,5 +220,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), true, 4)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic); } } diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs index 6e0cc8aac23..5af3e9215c0 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs @@ -159,6 +159,9 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 1)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } #[test] diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs index e455e76ba43..d242bce8433 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs @@ -206,6 +206,9 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 6)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } #[test] diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs index 1909d9b453b..88af82e3cb2 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs @@ -120,5 +120,8 @@ mod tests { format!("{:?}", res.unwrap_err()), "DeviceAttribute(Error(9), false, 5)" ); + + // dropping gic_fd would double close the gic fd, so leak it + std::mem::forget(gic_fd); } } diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 5c08f95351a..80fc5a339df 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -299,5 +299,8 @@ mod tests { let res = set_mpstate(&vcpu, kvm_mp_state::default()); assert!(matches!(res, Err(VcpuError::SetMp(_))), "{:?}", res); + + // dropping vcpu would double close the fd, so leak it + std::mem::forget(vcpu); } } diff --git a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs index de970986da2..09e86b6968d 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs @@ -187,7 +187,6 @@ impl FileEngine { pub mod tests { #![allow(clippy::undocumented_unsafe_blocks)] use std::os::unix::ffi::OsStrExt; - use std::os::unix::io::FromRawFd; use vmm_sys_util::tempfile::TempFile; @@ -201,20 +200,6 @@ pub mod tests { // 2 pages of memory should be enough to test read/write ops and also dirty tracking. const MEM_LEN: usize = 8192; - macro_rules! assert_err { - ($expression:expr, $($pattern:tt)+) => { - match $expression { - Err(UserDataError { - user_data: _, - error: $($pattern)+, - }) => (), - ref err => { - panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), err); - } - } - }; - } - macro_rules! assert_sync_execution { ($expression:expr, $count:expr) => { match $expression { @@ -265,17 +250,7 @@ pub mod tests { #[test] fn test_sync() { - // Check invalid file let mem = create_mem(); - let file = unsafe { File::from_raw_fd(-2) }; - let mut engine = FileEngine::from_file(file, FileEngineType::Sync).unwrap(); - let res = engine.read(0, &mem, GuestAddress(0), 0, ()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::Seek(_e))); - let res = engine.write(0, &mem, GuestAddress(0), 0, ()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::Seek(_e))); - let res = engine.flush(()); - assert_err!(res, BlockIoError::Sync(sync_io::SyncIoError::SyncAll(_e))); - // Create backing file. let file = TempFile::new().unwrap().into_file(); let mut engine = FileEngine::from_file(file, FileEngineType::Sync).unwrap(); @@ -342,10 +317,6 @@ pub mod tests { #[test] fn test_async() { - // Check invalid file - let file = unsafe { File::from_raw_fd(-2) }; - FileEngine::<()>::from_file(file, FileEngineType::Async).unwrap_err(); - // Create backing file. let file = TempFile::new().unwrap().into_file(); let mut engine = FileEngine::<()>::from_file(file, FileEngineType::Async).unwrap(); diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index a17c25d7248..99941f5796a 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -1808,6 +1808,9 @@ pub mod tests { assert_eq!(th.txq.used.idx.get(), 1); assert!(&th.net().irq_trigger.has_pending_irq(IrqType::Vring)); th.txq.check_used_elem(0, 0, 0); + + // dropping th would double close the tap fd, so leak it + std::mem::forget(th); } #[test] @@ -2041,6 +2044,9 @@ pub mod tests { 1, th.simulate_event(NetEvent::Tap) ); + + // dropping th would double close the tap fd, so leak it + std::mem::forget(th); } #[test] diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 0f5b7e2d788..776b5ba960e 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -277,19 +277,6 @@ pub mod tests { let tap = Tap::open_named("").unwrap(); tap.set_vnet_hdr_size(16).unwrap(); tap.set_offload(0).unwrap(); - - let faulty_tap = Tap { - tap_file: unsafe { File::from_raw_fd(-2) }, - if_name: [0x01; 16], - }; - assert_eq!( - faulty_tap.set_vnet_hdr_size(16).unwrap_err().to_string(), - TapError::SetSizeOfVnetHdr(IoError::from_raw_os_error(9)).to_string() - ); - assert_eq!( - faulty_tap.set_offload(0).unwrap_err().to_string(), - TapError::SetOffloadFlags(IoError::from_raw_os_error(9)).to_string() - ); } #[test] diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 2e2bb36fb07..4e006f196d0 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -329,6 +329,9 @@ mod tests { err.err().unwrap().to_string(), "Error creating vcpu: Bad file descriptor (os error 9)".to_string() ); + + // dropping vm would double close the gic fd, so leak it + std::mem::forget(vm); } #[test] @@ -361,6 +364,9 @@ mod tests { kvm_ioctls::Error::new(9) )) ); + + // dropping vcpu would double close the gic fd, so leak it + std::mem::forget(vcpu); } #[test] diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index a1bb22d1bb7..4043691130d 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -715,8 +715,6 @@ impl Debug for VcpuState { mod tests { #![allow(clippy::undocumented_unsafe_blocks)] - use std::os::unix::io::AsRawFd; - use kvm_bindings::kvm_msr_entry; use kvm_ioctls::{Cap, Kvm}; @@ -874,7 +872,7 @@ mod tests { // Restore the state into the existing vcpu. let result1 = vcpu.restore_state(&state); assert!(result1.is_ok(), "{}", result1.unwrap_err()); - unsafe { libc::close(vcpu.fd.as_raw_fd()) }; + drop(vcpu); // Restore the state into a new vcpu. let (_vm, vcpu, _mem) = setup_vcpu(0x10000); From 73fe828ed624eefb16f4ac908b350d030f68eb76 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 14:41:56 +0000 Subject: [PATCH 092/464] chore: apply updated mdformat styles It seemingly finally got intelligent enough to realize we don't need all these backslashes on the brackets. Signed-off-by: Patrick Roy --- CHANGELOG.md | 101 ++++++++++++------------ FAQ.md | 9 +-- README.md | 18 ++--- docs/api_requests/actions.md | 2 +- docs/api_requests/block-io-engine.md | 2 +- docs/api_requests/block-vhost-user.md | 2 +- docs/formal-verification.md | 49 ++++++------ docs/hugepages.md | 2 +- docs/prod-host-setup.md | 8 +- docs/snapshotting/network-for-clones.md | 2 +- docs/snapshotting/snapshot-support.md | 2 +- tests/README.md | 37 ++++----- 12 files changed, 112 insertions(+), 122 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e7be8f518f..65ef73a1e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## \[Unreleased\] +## [Unreleased] ### Added @@ -26,14 +26,14 @@ and this project adheres to - [#4921](https://github.com/firecracker-microvm/firecracker/pull/4921): Fixed swagger `CpuConfig` definition to include missing aarch64-specific fields. -## \[1.10.1\] +## [1.10.1] ### Changed - [#4907](https://github.com/firecracker-microvm/firecracker/pull/4907): Bumped the snapshot version to 4.0.0, so users need to regenerate snapshots. -## \[1.10.0\] +## [1.10.0] ### Added @@ -90,7 +90,7 @@ and this project adheres to in the restore path. This was leading to inability to connect to the restored VM if the offload features were used. -## \[1.9.0\] +## [1.9.0] ### Added @@ -134,7 +134,7 @@ and this project adheres to different assumptions. This PR fixes the emulation code to set the TAP features based on the features accepted by the guest. -## \[1.8.0\] +## [1.8.0] ### Added @@ -227,7 +227,7 @@ and this project adheres to could lead to them seemingly getting stuck in sleep-related syscalls (see also https://github.com/firecracker-microvm/firecracker/pull/4099). -## \[1.7.0\] +## [1.7.0] ### Added @@ -304,7 +304,7 @@ and this project adheres to content is empty, because the 'Content-Length' header field was missing in a response. -## \[1.6.0\] +## [1.6.0] ### Added @@ -396,7 +396,7 @@ and this project adheres to "write-back" of all memory that was updated since the snapshot was originally loaded. -## \[1.5.0\] +## [1.5.0] ### Added @@ -462,10 +462,10 @@ and this project adheres to - Fixed a change in behavior of normalize host brand string that breaks Firecracker on external instances. -- Fixed the T2A CPU template not to unset the MMX bit - (CPUID.80000001h:EDX\[23\]) and the FXSR bit (CPUID.80000001h:EDX\[24\]). +- Fixed the T2A CPU template not to unset the MMX bit (CPUID.80000001h:EDX[23]) + and the FXSR bit (CPUID.80000001h:EDX[24]). - Fixed the T2A CPU template to set the RstrFpErrPtrs bit - (CPUID.80000008h:EBX\[2\]). + (CPUID.80000008h:EBX[2]). - Fixed a bug where Firecracker would crash during boot if a guest set up a virtio queue that partially overlapped with the MMIO gap. Now Firecracker instead correctly refuses to activate the corresponding virtio device. @@ -484,7 +484,7 @@ and this project adheres to misspelled param ("nomodules") being present at the command line, since this param will no longer be passed. -## \[1.4.0\] +## [1.4.0] ### Added @@ -499,8 +499,8 @@ and this project adheres to ### Changed -- Set FDP_EXCPTN_ONLY bit (CPUID.7h.0:EBX\[6\]) and ZERO_FCS_FDS bit - (CPUID.7h.0:EBX\[13\]) in Intel's CPUID normalization process. +- Set FDP_EXCPTN_ONLY bit (CPUID.7h.0:EBX[6]) and ZERO_FCS_FDS bit + (CPUID.7h.0:EBX[13]) in Intel's CPUID normalization process. ### Fixed @@ -521,10 +521,9 @@ and this project adheres to - Fixed passing through cache information from host in CPUID leaf 0x80000005. - Fixed the T2A CPU template to disable SVM (nested virtualization). - Fixed the T2A CPU template to set EferLmsleUnsupported bit - (CPUID.80000008h:EBX\[20\]), which indicates that EFER\[LMSLE\] is not - supported. + (CPUID.80000008h:EBX[20]), which indicates that EFER[LMSLE] is not supported. -## \[1.3.0\] +## [1.3.0] ### Added @@ -544,7 +543,7 @@ and this project adheres to - Fixed feature flags in T2 CPU template on Intel Ice Lake. -## \[1.2.0\] +## [1.2.0] ### Added @@ -589,7 +588,7 @@ and this project adheres to of Firecracker \<= 1.1.3. - Improved stability and security when saving CPU MSRs in snapshots. -## \[1.1.0\] +## [1.1.0] ### Added @@ -651,7 +650,7 @@ and this project adheres to - Fixed incosistency in the swagger definition with the current state of the `/vm/config` endpoint. -## \[1.0.0\] +## [1.0.0] ### Added @@ -726,7 +725,7 @@ and this project adheres to - Fix jailer's cgroup implementation to accept properties that contain multiple dots. -## \[0.25.0\] +## [0.25.0] ### Added @@ -785,7 +784,7 @@ and this project adheres to Epoch, as the name suggests. It was previously using a monotonic clock with an undefined starting point. -## \[0.24.0\] +## [0.24.0] ### Added @@ -822,7 +821,7 @@ and this project adheres to - Fixed inconsistency in YAML file InstanceInfo definition -## \[0.23.0\] +## [0.23.0] ### Added @@ -873,7 +872,7 @@ and this project adheres to - Changed `devtool build` to build jailer binary for `musl` only targets. Building jailer binary for `non-musl` targets have been removed. -## \[0.22.0\] +## [0.22.0] ### Added @@ -937,7 +936,7 @@ and this project adheres to - Segregated MMDS documentation in MMDS design documentation and MMDS user guide documentation. -## \[0.21.0\] +## [0.21.0] ### Added @@ -973,7 +972,7 @@ and this project adheres to functionality is available through the PATCH /drives API. See `docs/api_requests/patch-block.md`. -## \[0.20.0\] +## [0.20.0] ### Added @@ -1001,7 +1000,7 @@ and this project adheres to - Decreased release binary size by 10%. -## \[0.19.0\] +## [0.19.0] ### Added @@ -1044,7 +1043,7 @@ and this project adheres to - Changed the vsock property `id` to `vsock_id` so that the API client can be successfully generated from the swagger definition. -## \[0.18.0\] +## [0.18.0] ### Added @@ -1071,7 +1070,7 @@ and this project adheres to - Removed experimental support for vhost-based vsock devices. -## \[0.17.0\] +## [0.17.0] ### Added @@ -1082,7 +1081,7 @@ and this project adheres to - Added a signal handler for `SIGBUS` and `SIGSEGV` that immediately terminates the process upon intercepting the signal. - Added documentation for signal handling utilities. -- Added \[alpha\] aarch64 support. +- Added [alpha] aarch64 support. - Added metrics for successful read and write operations of MMDS, Net and Block devices. @@ -1097,11 +1096,11 @@ and this project adheres to - Incorrect handling of bind mounts within the jailed rootfs. - Corrected the guide for `Alpine` guest setup. -## \[0.16.0\] +## [0.16.0] ### Added -- Added \[alpha\] AMD support. +- Added [alpha] AMD support. - New `devtool` command: `prepare_release`. This updates the Firecracker version, crate dependencies and credits in preparation for a new release. - New `devtool` command: `tag`. This creates a new git tag for the specified @@ -1127,13 +1126,13 @@ and this project adheres to - Removed the `seccomp.bad_syscalls` metric. -## \[0.15.2\] +## [0.15.2] ### Fixed - Corrected the conditional compilation of the seccomp rule for `madvise`. -## \[0.15.1\] +## [0.15.1] ### Fixed @@ -1141,7 +1140,7 @@ and this project adheres to list to prevent Firecracker from terminating abruptly when allocating memory in certain conditions. -## \[0.15.0\] +## [0.15.0] ### Added @@ -1166,7 +1165,7 @@ and this project adheres to - Vsock devices can be attached when starting Firecracker using the jailer. - Vsock devices work properly when seccomp filtering is enabled. -## \[0.14.0\] +## [0.14.0] ### Added @@ -1186,7 +1185,7 @@ and this project adheres to - Fixed build with the `vsock` feature. -## \[0.13.0\] +## [0.13.0] ### Added @@ -1213,7 +1212,7 @@ and this project adheres to - Removed `InstanceHalt` from the list of possible actions. -## \[0.12.0\] +## [0.12.0] ### Added @@ -1243,7 +1242,7 @@ and this project adheres to - Ensure MMDS compatibility with C5's IMDS implementation. - Corrected the swagger specification to ensure `OpenAPI 2.0` compatibility. -## \[0.11.0\] +## [0.11.0] ### Added @@ -1273,13 +1272,13 @@ and this project adheres to - Fixed bug in `PATCH /drives`, whereby the ID in the path was not checked against the ID in the body. -## \[0.10.1\] +## [0.10.1] ### Fixed - The Swagger definition was corrected. -## \[0.10.0\] +## [0.10.0] ### Added @@ -1305,7 +1304,7 @@ and this project adheres to - The microVM ID prefixes each Firecracker log line. This ID also appears in the process `cmdline` so it's now possible to `ps | grep ` for it. -## \[0.9.0\] +## [0.9.0] ### Added @@ -1339,7 +1338,7 @@ and this project adheres to - Remove the `action_id` parameter for `InstanceStart`, both from the URI and the JSON request body. -## \[0.8.0\] +## [0.8.0] ### Added @@ -1354,7 +1353,7 @@ and this project adheres to - Replaced the `permissions` property of `/drives` resources with a boolean. - Removed the `state` property of `/drives` resources. -## \[0.7.0\] +## [0.7.0] ### Added @@ -1379,7 +1378,7 @@ and this project adheres to guest kernel boot. - Fixed network emulation to improve IO performance. -## \[0.6.0\] +## [0.6.0] ### Added @@ -1408,7 +1407,7 @@ and this project adheres to - It is now possible to create more than one network tun/tap interface inside a jailed Firecracker. -## \[0.5.0\] +## [0.5.0] ### Added @@ -1447,7 +1446,7 @@ and this project adheres to - Removed a leftover file generated by the logger unit tests. - Removed `firecracker-v1.0.yaml`. -## \[0.4.0\] +## [0.4.0] ### Added @@ -1498,7 +1497,7 @@ and this project adheres to - Removed `--vmm-no-api` command line option. Firecracker can only be started via the API. -## \[0.3.0\] +## [0.3.0] ### Added @@ -1534,7 +1533,7 @@ and this project adheres to - Removed support for attaching vsock devices. - Removed support for building Firecracker with glibc. -## \[0.2.0\] +## [0.2.0] ### Added @@ -1572,7 +1571,7 @@ and this project adheres to - Removed `api/swagger/firecracker-mvp.yaml`. - Removed `api/swagger/limiters.yaml`. -## \[0.1.1\] +## [0.1.1] ### Changed @@ -1587,7 +1586,7 @@ and this project adheres to - Fixed an issue which caused compilation problems, due to a compatibility breaking transitive dependency in the tokio suite of crates. -## \[0.1.0\] +## [0.1.0] ### Added diff --git a/FAQ.md b/FAQ.md index 6697ac9f4d1..e2c011c3b7d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -60,11 +60,10 @@ minimal required device model to the guest operating system while excluding non-essential functionality (only 6 emulated devices are available: virtio-net, virtio-balloon, virtio-block, virtio-vsock, serial console, and a minimal keyboard controller used only to stop the microVM). This, along with a -streamlined kernel loading process enables a \< 125 ms startup time and a \< 5 -MiB memory footprint. The Firecracker process also provides a RESTful control -API, handles resource rate limiting for microVMs, and provides a microVM -metadata service to enable the sharing of configuration data between the host -and guest. +streamlined kernel loading process enables a < 125 ms startup time and a < 5 MiB +memory footprint. The Firecracker process also provides a RESTful control API, +handles resource rate limiting for microVMs, and provides a microVM metadata +service to enable the sharing of configuration data between the host and guest. ### What operating systems are supported by Firecracker? diff --git a/README.md b/README.md index f98079fc81c..5805b76ba15 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ The **API endpoint** can be used to: - Add a [entropy device](docs/entropy.md) to the microVM. - Start the microVM using a given kernel image, root file system, and boot arguments. -- \[x86_64 only\] Stop the microVM. +- [x86_64 only] Stop the microVM. **Built-in Capabilities**: @@ -130,14 +130,14 @@ 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 | | | | -| m6a.metal | | | | -| m6g.metal | | | | -| m7g.metal | | | | +| 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 | | | | +| m6a.metal | | | | +| m6g.metal | | | | +| m7g.metal | | | | ## Known issues and Limitations diff --git a/docs/api_requests/actions.md b/docs/api_requests/actions.md index c72f12372dc..40700c359de 100644 --- a/docs/api_requests/actions.md +++ b/docs/api_requests/actions.md @@ -31,7 +31,7 @@ curl --unix-socket /tmp/firecracker.socket -i \ -d '{ "action_type": "FlushMetrics" }' ``` -## \[Intel and AMD only\] SendCtrlAltDel +## [Intel and AMD only] SendCtrlAltDel This action will send the CTRL+ALT+DEL key sequence to the microVM. By convention, this sequence has been used to trigger a soft reboot and, as such, diff --git a/docs/api_requests/block-io-engine.md b/docs/api_requests/block-io-engine.md index 8d8521bca3b..733aa374acd 100644 --- a/docs/api_requests/block-io-engine.md +++ b/docs/api_requests/block-io-engine.md @@ -6,7 +6,7 @@ system calls. Firecracker 1.0.0 adds support for an asynchronous block device IO engine. -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](#developer-preview-status) for more info. diff --git a/docs/api_requests/block-vhost-user.md b/docs/api_requests/block-vhost-user.md index 8325992caf4..4a3a4dee918 100644 --- a/docs/api_requests/block-vhost-user.md +++ b/docs/api_requests/block-vhost-user.md @@ -1,6 +1,6 @@ # Vhost-user block device -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](../RELEASE_POLICY.md#developer-preview-features) for more info. diff --git a/docs/formal-verification.md b/docs/formal-verification.md index 29ef16636dd..6a0c2d07574 100644 --- a/docs/formal-verification.md +++ b/docs/formal-verification.md @@ -143,45 +143,40 @@ Verification Time: 0.19135727s ## FAQ **Q:** What is the Kani verifier?\ -**A:** The -[Kani Rust Verifier](https://github.com/model-checking/kani) is a bit-precise -model checker for Rust. Kani is particularly useful for verifying unsafe code -blocks in Rust, where the +**A:** The [Kani Rust Verifier](https://github.com/model-checking/kani) is a +bit-precise model checker for Rust. Kani is particularly useful for verifying +unsafe code blocks in Rust, where the “[unsafe superpowers](https://doc.rust-lang.org/stable/book/ch19-01-unsafe-rust.html#unsafe-superpowers)" are unchecked by the compiler. **Q:** What safety properties does Kani verify?\ -**A:** Kani verifies memory -safety properties (e.g., invalid-pointer dereferences, out-of-bounds array -access), user-specified assertions (i.e., `assert!(...)`), the absence of -`panic!()`s (e.g., `unwrap()` on `None` values), and the absence of some types -of unexpected behavior (e.g., arithmetic overflows). For a full overview, see -the +**A:** Kani verifies memory safety properties (e.g., invalid-pointer +dereferences, out-of-bounds array access), user-specified assertions (i.e., +`assert!(...)`), the absence of `panic!()`s (e.g., `unwrap()` on `None` values), +and the absence of some types of unexpected behavior (e.g., arithmetic +overflows). For a full overview, see the [Kani documentation](https://model-checking.github.io/kani/tutorial-kinds-of-failure.html). **Q:** Do we expect all contributors to write harnesses for newly introduced code?\ -**A:** No. Kani is complementary to unit testing, and we do not have -target for “proof coverage”. We employ formal verification in especially -critical code areas. Generally we do not expect someone who might not be -familiar with formal tools to contribute harnesses. We do expect all contributed -code to pass verification though, just like we expect it to pass unit test! +**A:** No. Kani is complementary to unit testing, and we do not have target for +“proof coverage”. We employ formal verification in especially critical code +areas. Generally we do not expect someone who might not be familiar with formal +tools to contribute harnesses. We do expect all contributed code to pass +verification though, just like we expect it to pass unit test! **Q:** How should I report issues related to any Firecracker harnesses?\ -**A:** -Our Kani harnesses verify safety critical invariants. If you discover a flaw in -a harness, please report it using the +**A:** Our Kani harnesses verify safety critical invariants. If you discover a +flaw in a harness, please report it using the [security issue disclosure process](https://github.com/firecracker-microvm/firecracker/blob/main/SECURITY.md). -**Q:** How do I know which properties I should prove in the Kani -harness?\ -**A:** Generally, these are given by some sort of specification. This -can either be the function contract described in its document (e.g. what -relation between input and output do callers expect?), or even something formal -such as the TCP/IP standard. Don't forget to mention the specification in your -proof harness! +**Q:** How do I know which properties I should prove in the Kani harness?\ +**A:** Generally, these are given by some sort of specification. This can either +be the function contract described in its document (e.g. what relation between +input and output do callers expect?), or even something formal such as the +TCP/IP standard. Don't forget to mention the specification in your proof +harness! **Q:** Where do I debug a broken proof?\ -**A:** Check out the Kani book section -on +**A:** Check out the Kani book section on [debugging verification failures](https://model-checking.github.io/kani/debugging-verification-failures.html). diff --git a/docs/hugepages.md b/docs/hugepages.md index 0b4b994e04f..05b4e25b399 100644 --- a/docs/hugepages.md +++ b/docs/hugepages.md @@ -1,6 +1,6 @@ # Backing Guest Memory by Huge Pages -> \[!WARNING\] +> [!WARNING] > > Support is currently in **developer preview**. See > [this section](RELEASE_POLICY.md#developer-preview-features) for more info. diff --git a/docs/prod-host-setup.md b/docs/prod-host-setup.md index acf06a1e3d4..f046e31c735 100644 --- a/docs/prod-host-setup.md +++ b/docs/prod-host-setup.md @@ -254,18 +254,18 @@ echo "swap partitions present (Recommendation: no swap)" \ ### Mitigating hardware vulnerabilities -> \[!CAUTION\] +> [!CAUTION] > > Firecracker is not able to mitigate host's hardware vulnerabilities. Adequate > mitigations need to be put in place when configuring the host. -> \[!CAUTION\] +> [!CAUTION] > > Firecracker is designed to provide isolation boundaries between microVMs > running in different Firecracker processes. It is strongly recommended that > each Firecracker process corresponds to a workload of a single tenant. -> \[!CAUTION\] +> [!CAUTION] > > For security and stability reasons it is highly recommended to load updated > microcode as soon as possible. Aside from keeping the system firmware @@ -328,7 +328,7 @@ For vendor-specific recommendations, please consult the resources below: - ARM: [Speculative Processor Vulnerability](https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability) -##### \[ARM only\] Physical counter directly passed through to the guest +##### [ARM only] Physical counter directly passed through to the guest On ARM, the physical counter (i.e `CNTPCT`) it is returning the [actual EL1 physical counter value of the host][1]. From the discussions before diff --git a/docs/snapshotting/network-for-clones.md b/docs/snapshotting/network-for-clones.md index d0a44e89413..b997ba3687e 100644 --- a/docs/snapshotting/network-for-clones.md +++ b/docs/snapshotting/network-for-clones.md @@ -3,7 +3,7 @@ This document presents a strategy to ensure continued network connectivity for multiple clones created from a single Firecracker microVM snapshot. -> \[!CAUTION\] +> [!CAUTION] > > This should be considered as just an example to get you started, and we don't > claim this is a performant or secure setup. diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 75ffd306e25..c8d964ae89b 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -37,7 +37,7 @@ workload at that particular point in time. ### Supported platforms -> \[!WARNING\] +> [!WARNING] > > The Firecracker snapshot feature is in > [developer preview](../RELEASE_POLICY.md) on all CPU micro-architectures diff --git a/tests/README.md b/tests/README.md index bf7aba9a547..91fb2a9aeed 100644 --- a/tests/README.md +++ b/tests/README.md @@ -400,36 +400,33 @@ setting to achieve consistent performance. Please see the `test` section of `Q1:` *I have a shell script that runs my tests and I don't want to rewrite it.*\ -`A1:` Insofar as it makes sense, you should write it as a python test -function. However, you can always call the script from a shim python test -function. You can also add it as a microvm image resource in the s3 bucket (and -it will be made available under `microvm.slot.path`) or copy it over to a guest -filesystem as part of your test. +`A1:` Insofar as it makes sense, you should write it as a python test function. +However, you can always call the script from a shim python test function. You +can also add it as a microvm image resource in the s3 bucket (and it will be +made available under `microvm.slot.path`) or copy it over to a guest filesystem +as part of your test. `Q2:` *I want to add more tests that I don't want to commit to the Firecracker repository.*\ -`A2:` Before a testrun or test session, just add your test -directory under `tests/`. `pytest` will discover all tests in this tree. +`A2:` Before a testrun or test session, just add your test directory under +`tests/`. `pytest` will discover all tests in this tree. -`Q3:` *I want to have my own test fixtures, and not commit them in the -repo.*\ -`A3:` Add a `conftest.py` file in your test directory, and place your -fixtures there. `pytest` will bring them into scope for all your tests. +`Q3:` *I want to have my own test fixtures, and not commit them in the repo.*\ +`A3:` Add a `conftest.py` file in your test directory, and place your fixtures +there. `pytest` will bring them into scope for all your tests. `Q4:` *I want to use more/other microvm test images, but I don't want to add them to the common s3 bucket.*\ -`A4:` Add your custom images to the `build/img` -subdirectory in the Firecracker source tree. This directory is bind-mounted in -the container and used as a local image cache. +`A4:` Add your custom images to the `build/img` subdirectory in the Firecracker +source tree. This directory is bind-mounted in the container and used as a local +image cache. `Q5:` *How can I get live logger output from the tests?*\ -`A5:` Accessing -**pytest.ini** will allow you to modify logger settings. +`A5:` Accessing **pytest.ini** will allow you to modify logger settings. `Q6:` *Is there a way to speed up integration tests execution time?*\ -`A6:` You -can narrow down the test selection as described in the **Running** section. For -example: +`A6:` You can narrow down the test selection as described in the **Running** +section. For example: 1. Pass the `-k substring` option to pytest to only run a subset of tests by specifying a part of their name. @@ -643,6 +640,6 @@ sudo pip3 install pytest ipython requests psutil tenacity filelock "urllib3<2.0" sudo env PYTHONPATH=tests HOME=$HOME ~/.local/bin/ipython3 -i tools/sandbox.py -- --binary-dir ../repro/v1.4.1 ``` -> \[!WARNING\] +> [!WARNING] > > **Notice this runs as root!** From cdbfac04dd6719dd72856196ef9d045e8d37023e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 15:40:44 +0000 Subject: [PATCH 093/464] fix: suppress dead code warnings in cache_info.rs The unittests here rely on the cfg(not(test)) antipattern for mocking, which new rust compiler interprets as the production version of the structs being dead-code when running unittests. Refactoring this to eliminate mocking is difficult, because fdt unit tests rely on the mocks removing all host-specific information from the cpu FDT nodes (particularly cache information, which in prod is read from the host sysfs, but in test mode is some dummy mock values). Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/cache_info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vmm/src/arch/aarch64/cache_info.rs b/src/vmm/src/arch/aarch64/cache_info.rs index cd61cabeb02..fd7d6e0a2ea 100644 --- a/src/vmm/src/arch/aarch64/cache_info.rs +++ b/src/vmm/src/arch/aarch64/cache_info.rs @@ -45,6 +45,7 @@ pub(crate) struct CacheEntry { } #[derive(Debug)] +#[cfg_attr(test, allow(dead_code))] struct HostCacheStore { cache_dir: PathBuf, } @@ -206,6 +207,7 @@ impl CacheType { } } +#[cfg_attr(test, allow(unused))] fn readln_special>(file_path: &T) -> Result { let line = fs::read_to_string(file_path)?; Ok(line.trim_end().to_string()) From 70c295e586f8aa916d942c68176c453ccf6d6e2c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 15:24:54 +0000 Subject: [PATCH 094/464] test: update changelog validation to match new mdformat with new mdformat we no longer need to wrap level 2 headings in escaped brackets, just normal brackets. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_repo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/style/test_repo.py b/tests/integration_tests/style/test_repo.py index 90a1e9450e1..299f89f6cdb 100644 --- a/tests/integration_tests/style/test_repo.py +++ b/tests/integration_tests/style/test_repo.py @@ -44,8 +44,8 @@ def test_repo_validate_changelog(): errors = [] for lineno, line in enumerate(changelog, start=1): if line.startswith("## "): - if not re.match(r"^## \\\[.+\\\]$", line): - msg = "Level 2 headings (versions) should be wrapped in \\[\\]" + if not re.match(r"^## \[.+\]$", line): + msg = "Level 2 headings (versions) should be wrapped in []" errors.append((lineno, msg, line)) if line.startswith("### "): if not re.match(r"^### (Added|Changed|Deprecated|Removed|Fixed)$", line): From c8fa501fb24eabcb8dc239a6cd1b9fd6e32199f0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 10 Dec 2024 17:27:32 +0000 Subject: [PATCH 095/464] chore: update release-prepare.sh to deal with less escaped markdown Thanks to mdformat no longer escaping brackets everywhere, we can simplify a regex. Signed-off-by: Patrick Roy --- tools/release-prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/release-prepare.sh b/tools/release-prepare.sh index 30c32316944..f74334443ee 100755 --- a/tools/release-prepare.sh +++ b/tools/release-prepare.sh @@ -54,7 +54,7 @@ $FC_TOOLS_DIR/update-credits.sh # Update changelog. say "Updating changelog..." -sed -i "s/\\\\\[Unreleased\\\\\]/\\\\\[$version\\\\\]/g" "$FC_ROOT_DIR/CHANGELOG.md" +sed -i "s/\[Unreleased\]/\[$version\]/g" "$FC_ROOT_DIR/CHANGELOG.md" # Add all changed files git add -u From 17846a3c9cef95a8571f221bc571f58c10a281bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 2 Dec 2024 22:21:03 +0100 Subject: [PATCH 096/464] tests: move pylint config to pyproject.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It makes it easier to configure pylint Signed-off-by: Pablo Barbáchano --- tests/integration_tests/style/test_python.py | 12 +---- tests/pyproject.toml | 47 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/tests/integration_tests/style/test_python.py b/tests/integration_tests/style/test_python.py index b04b93dace2..447a1969daa 100644 --- a/tests/integration_tests/style/test_python.py +++ b/tests/integration_tests/style/test_python.py @@ -28,17 +28,7 @@ def test_python_pylint(): Test that python code passes linter checks. """ # List of linter commands that should be executed for each file - linter_cmd = ( - # Pylint - "pylint --jobs=0 --persistent=no --score=no " - '--output-format=colorized --attr-rgx="[a-z_][a-z0-9_]{1,30}$" ' - '--argument-rgx="[a-z_][a-z0-9_]{1,35}$" ' - '--variable-rgx="[a-z_][a-z0-9_]{1,30}$" --disable=' - "fixme,too-many-instance-attributes,import-error," - "too-many-locals,too-many-arguments,consider-using-f-string," - "consider-using-with,implicit-str-concat,line-too-long,redefined-outer-name," - "broad-exception-raised,duplicate-code,too-many-positional-arguments tests tools .buildkite/*.py" - ) + linter_cmd = "pylint --rcfile tests/pyproject.toml --output-format=colorized tests/ tools/ .buildkite/*.py" run( linter_cmd, # we let pytest capture stdout/stderr for us diff --git a/tests/pyproject.toml b/tests/pyproject.toml index a81f188f996..19a77b5e190 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -8,3 +8,50 @@ exclude = "/(\\.direnv|\\.eggs|\\.git|\\.hg|\\.mypy_cache|\\.nox|\\.tox|\\.venv| # https://pycqa.github.io/isort/docs/configuration/multi_line_output_modes.html multi_line_output = 3 profile = "black" + +[tool.pylint.main] + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use, and will cap the count on Windows to +# avoid hangs. +jobs = 0 + +score = false + +# Pickle collected data for later comparisons. +persistent = false + +# Disable the message, report, category or checker with the given id(s). You can +# either give multiple identifiers separated by comma (,) or put this option +# multiple times (only on the command line, not in the configuration file where +# it should appear only once). You can also use "--disable=all" to disable +# everything first and then re-enable specific checks. For example, if you want +# to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable = [ + "raw-checker-failed", + "bad-inline-option", + "locally-disabled", + "file-ignored", + "suppressed-message", + "useless-suppression", + "deprecated-pragma", + "use-implicit-booleaness-not-comparison-to-string", + "use-implicit-booleaness-not-comparison-to-zero", + "use-symbolic-message-instead", + "fixme", + "too-many-instance-attributes", + "import-error", + "too-many-locals", + "too-many-arguments", + "consider-using-f-string", + "consider-using-with", + "implicit-str-concat", + "line-too-long", + "redefined-outer-name", + "broad-exception-raised", + "duplicate-code", + "too-many-positional-arguments", +] From 545b47ded00569683827c5c6b0edd158332199b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 2 Dec 2024 22:37:15 +0100 Subject: [PATCH 097/464] style: disable pylint too-few-public-methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I think this lint is not useful, and makes writing small classes more difficult than it needs to be. Signed-off-by: Pablo Barbáchano --- tests/framework/http_api.py | 2 -- tests/framework/properties.py | 1 - tests/framework/state_machine.py | 2 -- tests/framework/utils.py | 1 - tests/integration_tests/functional/test_serial_io.py | 6 +++--- tests/pyproject.toml | 1 + 6 files changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/framework/http_api.py b/tests/framework/http_api.py index a1ee37174b0..ea8efd3df4f 100644 --- a/tests/framework/http_api.py +++ b/tests/framework/http_api.py @@ -3,8 +3,6 @@ """A simple HTTP client for the Firecracker API""" -# pylint:disable=too-few-public-methods - import urllib from http import HTTPStatus diff --git a/tests/framework/properties.py b/tests/framework/properties.py index 7dd1cb46588..7072a2ff3ca 100644 --- a/tests/framework/properties.py +++ b/tests/framework/properties.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # pylint:disable=broad-except -# pylint:disable=too-few-public-methods """ Metadata we want to attach to tests for further analysis and troubleshooting diff --git a/tests/framework/state_machine.py b/tests/framework/state_machine.py index 97975c75526..1d8dd664e6b 100644 --- a/tests/framework/state_machine.py +++ b/tests/framework/state_machine.py @@ -3,8 +3,6 @@ """Defines a stream based string matcher and a generic state object.""" -# Too few public methods (1/2) (too-few-public-methods) -# pylint: disable=R0903 class MatchStaticString: """Match a static string versus input.""" diff --git a/tests/framework/utils.py b/tests/framework/utils.py index a8715f00e94..e71302545c9 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -196,7 +196,6 @@ def __del__(self): self.proc.kill() -# pylint: disable=too-few-public-methods class CpuMap: """Cpu map from real cpu cores to containers visible cores. diff --git a/tests/integration_tests/functional/test_serial_io.py b/tests/integration_tests/functional/test_serial_io.py index db1521d4a44..aee9047f531 100644 --- a/tests/integration_tests/functional/test_serial_io.py +++ b/tests/integration_tests/functional/test_serial_io.py @@ -16,7 +16,7 @@ PLATFORM = platform.machine() -class WaitTerminal(TestState): # pylint: disable=too-few-public-methods +class WaitTerminal(TestState): """Initial state when we wait for the login prompt.""" def handle_input(self, serial, input_char) -> TestState: @@ -27,7 +27,7 @@ def handle_input(self, serial, input_char) -> TestState: return self -class WaitIDResult(TestState): # pylint: disable=too-few-public-methods +class WaitIDResult(TestState): """Wait for the console to show the result of the 'id' shell command.""" def handle_input(self, unused_serial, input_char) -> TestState: @@ -37,7 +37,7 @@ def handle_input(self, unused_serial, input_char) -> TestState: return self -class TestFinished(TestState): # pylint: disable=too-few-public-methods +class TestFinished(TestState): """Test complete and successful.""" def handle_input(self, unused_serial, _) -> TestState: diff --git a/tests/pyproject.toml b/tests/pyproject.toml index 19a77b5e190..70df5a75331 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -54,4 +54,5 @@ disable = [ "broad-exception-raised", "duplicate-code", "too-many-positional-arguments", + "too-few-public-methods", ] From fe8239232e6868df6366bcb10f9491eccaeac4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 5 Nov 2024 13:25:40 +0100 Subject: [PATCH 098/464] tests: cleanup test_seccomp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - convert inline JSON to dicts - use pytest temporary files instead of tempfile - create a seccompiler fixture to make running it easy Signed-off-by: Pablo Barbáchano --- tests/integration_tests/security/conftest.py | 29 +++ .../security/test_custom_seccomp.py | 198 +++++------------- .../security/test_seccomp.py | 196 ++++++----------- 3 files changed, 136 insertions(+), 287 deletions(-) create mode 100644 tests/integration_tests/security/conftest.py diff --git a/tests/integration_tests/security/conftest.py b/tests/integration_tests/security/conftest.py new file mode 100644 index 00000000000..1cce3067b2f --- /dev/null +++ b/tests/integration_tests/security/conftest.py @@ -0,0 +1,29 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Fixtures for security tests""" + +import json +from pathlib import Path + +import pytest + +from host_tools.cargo_build import run_seccompiler_bin + + +@pytest.fixture() +def seccompiler(tmp_path): + "A seccompiler helper fixture" + + class Seccompiler: + "A seccompiler helper class" + + def compile(self, data: dict, basic=False) -> Path: + "Use seccompiler-bin to compile a filter from a dict" + inp = tmp_path / "input.json" + inp.write_text(json.dumps(data)) + bpf = tmp_path / "output.bpfmap" + run_seccompiler_bin(bpf_path=bpf, json_path=inp, basic=basic) + return bpf + + return Seccompiler() diff --git a/tests/integration_tests/security/test_custom_seccomp.py b/tests/integration_tests/security/test_custom_seccomp.py index 5fffb83f6cc..05f9b9aa96e 100644 --- a/tests/integration_tests/security/test_custom_seccomp.py +++ b/tests/integration_tests/security/test_custom_seccomp.py @@ -2,179 +2,76 @@ # SPDX-License-Identifier: Apache-2.0 """Tests that the --seccomp-filter parameter works as expected.""" -import os import platform -import tempfile import time +from pathlib import Path -import pytest import requests from framework import utils -from host_tools.cargo_build import run_seccompiler_bin -def _custom_filter_setup(test_microvm, json_filter): - json_temp = tempfile.NamedTemporaryFile(delete=False) - json_temp.write(json_filter) - json_temp.flush() +def install_filter(microvm, bpf_path): + """Install seccomp filter in microvm.""" + microvm.create_jailed_resource(bpf_path) + microvm.jailer.extra_args.update({"seccomp-filter": bpf_path.name}) - bpf_path = os.path.join(test_microvm.path, "bpf.out") - run_seccompiler_bin(bpf_path=bpf_path, json_path=json_temp.name) +def test_allow_all(uvm_plain, seccompiler): + """Test --seccomp-filter, allowing all syscalls.""" + seccomp_filter = { + thread: {"default_action": "allow", "filter_action": "trap", "filter": []} + for thread in ["vmm", "api", "vcpu"] + } - os.unlink(json_temp.name) - test_microvm.create_jailed_resource(bpf_path) - test_microvm.jailer.extra_args.update({"seccomp-filter": "bpf.out"}) - - -def _config_file_setup(test_microvm, vm_config_file): - test_microvm.create_jailed_resource(test_microvm.kernel_file) - test_microvm.create_jailed_resource(test_microvm.rootfs_file) - - vm_config_path = os.path.join(test_microvm.path, os.path.basename(vm_config_file)) - with open(vm_config_file, encoding="utf-8") as f1: - with open(vm_config_path, "w", encoding="utf-8") as f2: - for line in f1: - f2.write(line) - test_microvm.create_jailed_resource(vm_config_path) - test_microvm.jailer.extra_args = {"config-file": os.path.basename(vm_config_file)} - - test_microvm.jailer.extra_args.update({"no-api": None}) - - -def test_allow_all(uvm_plain): - """ - Test --seccomp-filter, allowing all syscalls. - """ + bpf_path = seccompiler.compile(seccomp_filter) test_microvm = uvm_plain - - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Api": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Vcpu": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - } - }""".encode( - "utf-8" - ), - ) - + install_filter(test_microvm, bpf_path) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_working_filter(uvm_plain): - """ - Test --seccomp-filter, rejecting some dangerous syscalls. - """ - test_microvm = uvm_plain +def test_working_filter(uvm_plain, seccompiler): + """Test --seccomp-filter, rejecting some dangerous syscalls.""" - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { - "default_action": "allow", - "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve" - } - ] - }, - "Api": { - "default_action": "allow", - "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve" - } - ] - }, - "Vcpu": { + seccomp_filter = { + thread: { "default_action": "allow", "filter_action": "kill_process", - "filter": [ - { - "syscall": "clone" - }, - { - "syscall": "execve", - "comment": "sample comment" - } - ] + "filter": [{"syscall": "clone"}, {"syscall": "execve"}], } - }""".encode( - "utf-8" - ), - ) + for thread in ["vmm", "api", "vcpu"] + } + bpf_path = seccompiler.compile(seccomp_filter) + test_microvm = uvm_plain + install_filter(test_microvm, bpf_path) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() # level should be 2, with no additional errors utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_failing_filter(uvm_plain): - """ - Test --seccomp-filter, denying some needed syscalls. - """ - test_microvm = uvm_plain +def test_failing_filter(uvm_plain, seccompiler): + """Test --seccomp-filter, denying some needed syscalls.""" - _custom_filter_setup( - test_microvm, - """{ - "Vmm": { + seccomp_filter = { + "vmm": {"default_action": "allow", "filter_action": "trap", "filter": []}, + "api": {"default_action": "allow", "filter_action": "trap", "filter": []}, + "vcpu": { "default_action": "allow", "filter_action": "trap", - "filter": [] + "filter": [{"syscall": "ioctl"}], }, - "Api": { - "default_action": "allow", - "filter_action": "trap", - "filter": [] - }, - "Vcpu": { - "default_action": "allow", - "filter_action": "trap", - "filter": [ - { - "syscall": "ioctl" - } - ] - } - }""".encode( - "utf-8" - ), - ) + } + bpf_path = seccompiler.compile(seccomp_filter) + test_microvm = uvm_plain + install_filter(test_microvm, bpf_path) test_microvm.spawn() test_microvm.basic_config(vcpu_count=1) @@ -190,8 +87,7 @@ def test_failing_filter(uvm_plain): # Check the logger output ioctl_num = 16 if platform.machine() == "x86_64" else 29 test_microvm.check_log_message( - "Shutting down VM after intercepting a bad" - " syscall ({})".format(str(ioctl_num)) + f"Shutting down VM after intercepting a bad syscall ({ioctl_num})" ) # Check the metrics @@ -208,28 +104,28 @@ def test_failing_filter(uvm_plain): test_microvm.mark_killed() -@pytest.mark.parametrize("vm_config_file", ["framework/vm_config.json"]) -def test_invalid_bpf(uvm_plain, vm_config_file): - """ - Test that FC does not start, given an invalid binary filter. - """ +def test_invalid_bpf(uvm_plain): + """Test that FC does not start, given an invalid binary filter.""" test_microvm = uvm_plain # Configure VM from JSON. Otherwise, the test will error because # the process will be killed before configuring the API socket. - _config_file_setup(uvm_plain, vm_config_file) + test_microvm.create_jailed_resource(test_microvm.kernel_file) + test_microvm.create_jailed_resource(test_microvm.rootfs_file) - bpf_path = os.path.join(test_microvm.path, "bpf.out") - file = open(bpf_path, "w", encoding="utf-8") - file.write("Invalid BPF!") - file.close() + vm_config_file = Path("framework/vm_config.json") + test_microvm.create_jailed_resource(vm_config_file) + test_microvm.jailer.extra_args = {"config-file": vm_config_file.name} + test_microvm.jailer.extra_args.update({"no-api": None}) + bpf_path = Path(test_microvm.path) / "bpf.out" + bpf_path.write_bytes(b"Invalid BPF!") test_microvm.create_jailed_resource(bpf_path) - test_microvm.jailer.extra_args.update({"seccomp-filter": "bpf.out"}) + test_microvm.jailer.extra_args.update({"seccomp-filter": bpf_path.name}) test_microvm.spawn() - # give time for the process to get killed time.sleep(1) + assert "Seccomp error: Filter deserialization failed" in test_microvm.log_data test_microvm.mark_killed() diff --git a/tests/integration_tests/security/test_seccomp.py b/tests/integration_tests/security/test_seccomp.py index 0fa9aefafcb..8ae87271daf 100644 --- a/tests/integration_tests/security/test_seccomp.py +++ b/tests/integration_tests/security/test_seccomp.py @@ -2,91 +2,47 @@ # SPDX-License-Identifier: Apache-2.0 """Tests that the seccomp filters don't let denied syscalls through.""" -import json as json_lib +import json import os import platform -import tempfile +from pathlib import Path from framework import utils -from host_tools.cargo_build import run_seccompiler_bin + +ARCH = platform.machine() def _get_basic_syscall_list(): """Return the JSON list of syscalls that the demo jailer needs.""" - if platform.machine() == "x86_64": - sys_list = [ - "rt_sigprocmask", - "rt_sigaction", - "execve", - "mmap", - "mprotect", + sys_list = [ + "rt_sigprocmask", + "rt_sigaction", + "execve", + "mmap", + "mprotect", + "set_tid_address", + "read", + "close", + "brk", + "sched_getaffinity", + "sigaltstack", + "munmap", + "exit_group", + ] + if ARCH == "x86_64": + sys_list += [ "arch_prctl", - "set_tid_address", "readlink", "open", - "read", - "close", - "brk", - "sched_getaffinity", - "sigaltstack", - "munmap", - "exit_group", "poll", ] - else: - # platform.machine() == "aarch64" - sys_list = [ - "rt_sigprocmask", - "rt_sigaction", - "execve", - "mmap", - "mprotect", - "set_tid_address", - "read", - "close", - "brk", - "sched_getaffinity", - "sigaltstack", - "munmap", - "exit_group", - "ppoll", - ] - - json = "" - for syscall in sys_list[0:-1]: - json += """ - {{ - "syscall": \"{}\" - }}, - """.format( - syscall - ) - - json += """ - {{ - "syscall": \"{}\" - }} - """.format( - sys_list[-1] - ) - - return json - - -def _run_seccompiler_bin(json_data, basic=False): - json_temp = tempfile.NamedTemporaryFile(delete=False) - json_temp.write(json_data.encode("utf-8")) - json_temp.flush() - - bpf_temp = tempfile.NamedTemporaryFile(delete=False) + elif ARCH == "aarch64": + sys_list += ["ppoll"] - run_seccompiler_bin(bpf_path=bpf_temp.name, json_path=json_temp.name, basic=basic) + return sys_list - os.unlink(json_temp.name) - return bpf_temp.name - -def test_seccomp_ls(bin_seccomp_paths): +def test_seccomp_ls(bin_seccomp_paths, seccompiler): """ Assert that the seccomp filter denies an unallowed syscall. """ @@ -99,32 +55,26 @@ def test_seccomp_ls(bin_seccomp_paths): demo_jailer = bin_seccomp_paths["demo_jailer"] assert os.path.exists(demo_jailer) - json_filter = """{{ - "main": {{ + json_filter = { + "main": { "default_action": "trap", "filter_action": "allow", - "filter": [ - {} - ] - }} - }}""".format( - _get_basic_syscall_list() - ) + "filter": [{"syscall": x} for x in _get_basic_syscall_list()], + } + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) # Run the mini jailer. outcome = utils.run_cmd([demo_jailer, ls_command_path, bpf_path], shell=False) - os.unlink(bpf_path) - # The seccomp filters should send SIGSYS (31) to the binary. `ls` doesn't # handle it, so it will exit with error. assert outcome.returncode != 0 -def test_advanced_seccomp(bin_seccomp_paths): +def test_advanced_seccomp(bin_seccomp_paths, seccompiler): """ Test seccompiler-bin with `demo_jailer`. @@ -143,39 +93,37 @@ def test_advanced_seccomp(bin_seccomp_paths): assert os.path.exists(demo_harmless) assert os.path.exists(demo_malicious) - json_filter = """{{ - "main": {{ + json_filter = { + "main": { "default_action": "trap", "filter_action": "allow", "filter": [ - {}, - {{ + *[{"syscall": x} for x in _get_basic_syscall_list()], + { "syscall": "write", "args": [ - {{ + { "index": 0, "type": "dword", "op": "eq", "val": 1, - "comment": "stdout fd" - }}, - {{ + "comment": "stdout fd", + }, + { "index": 2, "type": "qword", "op": "eq", "val": 14, - "comment": "nr of bytes" - }} - ] - }} - ] - }} - }}""".format( - _get_basic_syscall_list() - ) + "comment": "nr of bytes", + }, + ], + }, + ], + } + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) # Run the mini jailer for harmless binary. outcome = utils.run_cmd([demo_jailer, demo_harmless, bpf_path], shell=False) @@ -189,10 +137,8 @@ def test_advanced_seccomp(bin_seccomp_paths): # The demo malicious binary should have received `SIGSYS`. assert outcome.returncode == -31 - os.unlink(bpf_path) - # Run seccompiler-bin with `--basic` flag. - bpf_path = _run_seccompiler_bin(json_filter, basic=True) + bpf_path = seccompiler.compile(json_filter, basic=True) # Run the mini jailer for malicious binary. outcome = utils.run_cmd([demo_jailer, demo_malicious, bpf_path], shell=False) @@ -201,28 +147,20 @@ def test_advanced_seccomp(bin_seccomp_paths): # disables all argument checks. assert outcome.returncode == 0 - os.unlink(bpf_path) - # Run the mini jailer with an empty allowlist. It should trap on any # syscall. - json_filter = """{ - "main": { - "default_action": "trap", - "filter_action": "allow", - "filter": [] - } - }""" + json_filter = { + "main": {"default_action": "trap", "filter_action": "allow", "filter": []} + } # Run seccompiler-bin. - bpf_path = _run_seccompiler_bin(json_filter) + bpf_path = seccompiler.compile(json_filter) outcome = utils.run_cmd([demo_jailer, demo_harmless, bpf_path], shell=False) # The demo binary should have received `SIGSYS`. assert outcome.returncode == -31 - os.unlink(bpf_path) - def test_no_seccomp(uvm_plain): """ @@ -231,11 +169,8 @@ def test_no_seccomp(uvm_plain): test_microvm = uvm_plain test_microvm.jailer.extra_args.update({"no-seccomp": None}) test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "0") @@ -245,15 +180,12 @@ def test_default_seccomp_level(uvm_plain): """ test_microvm = uvm_plain test_microvm.spawn() - test_microvm.basic_config() - test_microvm.start() - utils.assert_seccomp_level(test_microvm.firecracker_pid, "2") -def test_seccomp_rust_panic(bin_seccomp_paths): +def test_seccomp_rust_panic(bin_seccomp_paths, seccompiler): """ Test seccompiler-bin with `demo_panic`. @@ -266,19 +198,15 @@ def test_seccomp_rust_panic(bin_seccomp_paths): demo_panic = bin_seccomp_paths["demo_panic"] assert os.path.exists(demo_panic) - fc_filters_path = "../resources/seccomp/{}-unknown-linux-musl.json".format( - platform.machine() - ) - with open(fc_filters_path, "r", encoding="utf-8") as fc_filters: - filter_threads = list(json_lib.loads(fc_filters.read())) + fc_filters = Path(f"../resources/seccomp/{ARCH}-unknown-linux-musl.json") + fc_filters_data = json.loads(fc_filters.read_text(encoding="ascii")) + filter_threads = list(fc_filters_data) - bpf_temp = tempfile.NamedTemporaryFile(delete=False) - run_seccompiler_bin(bpf_path=bpf_temp.name, json_path=fc_filters_path) - bpf_path = bpf_temp.name + bpf_path = seccompiler.compile(fc_filters_data) # Run the panic binary with all filters. for thread in filter_threads: - code, _, _ = utils.run_cmd([demo_panic, bpf_path, thread], shell=False) + code, _, _ = utils.run_cmd([demo_panic, str(bpf_path), thread], shell=False) # The demo panic binary should have terminated with SIGABRT # and not with a seccomp violation. # On a seccomp violation, the program exits with code -31 for @@ -286,8 +214,4 @@ def test_seccomp_rust_panic(bin_seccomp_paths): # is for SIGABRT. assert ( code == -6 - ), "Panic binary failed with exit code {} on {} " "filters.".format( - code, thread - ) - - os.unlink(bpf_path) + ), f"Panic binary failed with exit code {code} on {thread} filters." From 20275947ab2d241452d090b2bc6efb839685b8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 5 Dec 2024 16:18:39 +0100 Subject: [PATCH 099/464] docs: reflect that seccompiler --basic filters are deprecated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit seccompiler --basic filters are deprecated Signed-off-by: Pablo Barbáchano --- DEPRECATED.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DEPRECATED.md b/DEPRECATED.md index ca9068d773d..e20e4af628a 100644 --- a/DEPRECATED.md +++ b/DEPRECATED.md @@ -19,3 +19,5 @@ a future major Firecracker release, in accordance with our - \[[#4428](https://github.com/firecracker-microvm/firecracker/pull/4428)\] Booting microVMs using MPTable and command line parameters for VirtIO devices. The functionality is substituted with ACPI. +- \[[#2628](https://github.com/firecracker-microvm/firecracker/pull/2628)\] The + `--basic` parameter of `seccompiler-bin`. From 979cf1b23eaa874f6befc60409139945d702ffbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 9 Dec 2024 23:50:50 +0100 Subject: [PATCH 100/464] tests: add test to validate seccomp filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test to validate that a seccomp filter works as defined in the JSON description. To do this we use a simple C program that just loads a given seccomp filter and calls a syscall also given in the arguments. Signed-off-by: Pablo Barbáchano --- tests/host_tools/test_syscalls.c | 77 ++++++++++ .../security/test_seccomp_validate.py | 138 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 tests/host_tools/test_syscalls.c create mode 100644 tests/integration_tests/security/test_seccomp_validate.py diff --git a/tests/host_tools/test_syscalls.c b/tests/host_tools/test_syscalls.c new file mode 100644 index 00000000000..6a58edf0983 --- /dev/null +++ b/tests/host_tools/test_syscalls.c @@ -0,0 +1,77 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// This is used by `test_seccomp_validate.py` + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +void install_bpf_filter(char *bpf_file) { + int fd = open(bpf_file, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + struct stat sb; + if (fstat(fd, &sb) == -1) { + perror("stat"); + exit(EXIT_FAILURE); + } + size_t size = sb.st_size; + size_t insn_len = size / sizeof(struct sock_filter); + struct sock_filter *filterbuf = (struct sock_filter*)malloc(size); + if (read(fd, filterbuf, size) == -1) { + perror("read"); + exit(EXIT_FAILURE); + } + + /* Install seccomp filter */ + struct sock_fprog prog = { + .len = (unsigned short)(insn_len), + .filter = filterbuf, + }; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + exit(EXIT_FAILURE); + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { + perror("prctl(SECCOMP)"); + exit(EXIT_FAILURE); + } +} + + +int main(int argc, char **argv) { + /* parse arguments */ + if (argc < 3) { + fprintf(stderr, "Usage: %s BPF_FILE ARG0..\n", argv[0]); + exit(EXIT_FAILURE); + } + char *bpf_file = argv[1]; + long syscall_id = atoi(argv[2]); + long arg0, arg1, arg2, arg3; + arg0 = arg1 = arg2 = arg3 = 0; + if (argc > 3) arg0 = atoi(argv[3]); + if (argc > 4) arg1 = atoi(argv[4]); + if (argc > 5) arg2 = atoi(argv[5]); + if (argc > 6) arg3 = atoi(argv[6]); + + /* read seccomp filter from file */ + if (strcmp(bpf_file, "/dev/null") != 0) { + install_bpf_filter(bpf_file); + } + + long res = syscall(syscall_id, arg0, arg1, arg2, arg3); + printf("%ld\n", res); + return EXIT_SUCCESS; +} diff --git a/tests/integration_tests/security/test_seccomp_validate.py b/tests/integration_tests/security/test_seccomp_validate.py new file mode 100644 index 00000000000..5a0be067899 --- /dev/null +++ b/tests/integration_tests/security/test_seccomp_validate.py @@ -0,0 +1,138 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Test that validates that seccompiler filters work as expected""" + +import json +import platform +import resource +import struct +from pathlib import Path + +import pytest +import seccomp + +from framework import utils +from host_tools import cargo_build + +ARCH = platform.machine() + + +@pytest.fixture(scope="session") +def bin_test_syscall(test_fc_session_root_path): + """Build the test_syscall binary.""" + test_syscall_bin = Path(test_fc_session_root_path) / "test_syscall" + cargo_build.gcc_compile("host_tools/test_syscalls.c", test_syscall_bin) + assert test_syscall_bin.exists() + yield test_syscall_bin + + +class BpfMapReader: + """ + Simple reader for the files that seccompiler-bin produces + + The files are serialized with bincode[1] in format that is easy to parse. + + sock_filter = + BpfProgram = Vec + BpfMap = BTreeMap(str, BpfProgram) + str = Vec + + [1] https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md + """ + + INSN_FMT = " Date: Fri, 29 Nov 2024 11:06:00 +0000 Subject: [PATCH 101/464] test: fix malformed f string in microvm_helpers.py My python version does not accept the precense of double quotes inside a double-quoted f-string. Use single quotes instead. Signed-off-by: Patrick Roy --- tests/framework/microvm_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/microvm_helpers.py b/tests/framework/microvm_helpers.py index f29ae84a9a0..b34da3c447e 100644 --- a/tests/framework/microvm_helpers.py +++ b/tests/framework/microvm_helpers.py @@ -242,6 +242,6 @@ def trace_cmd_guest(self, fns, cmd, port=4321): print("guest> trace-cmd record") host_ip = self.vm.iface["eth0"]["iface"].host_ip _guest_ps = self.vm.ssh.run( - f"trace-cmd record -N {host_ip}:{port} -p function {" ".join(fns)} {cmd}" + f"trace-cmd record -N {host_ip}:{port} -p function {' '.join(fns)} {cmd}" ) return list(Path(".").glob("trace.*.dat")) From b3d202b1926fe31daf534c28e2699566c36eb5aa Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 13:13:33 +0000 Subject: [PATCH 102/464] test: close stdout/stderr after timeout in utils.run_cmd If a command times out in utils.run_cmd, we kill the subprocess and try to get whatever partial output it wrote so far to generate an error message. We do this using `communicate`, which waits for stdout/stderr to close. Some processes pass their stdout and stderr to their children. In this case, killing the parent won't close the stdout/stderr, and so the proc.communicate() call in run_cmd will wait indefinitely (or until whatever is holding on the the other end of the pipe exits). Avoid this by explicitly closing our end of the stdout/stderr pipes. Signed-off-by: Patrick Roy --- tests/framework/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/framework/utils.py b/tests/framework/utils.py index e71302545c9..8bb1d8c744e 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -397,6 +397,12 @@ def run_cmd(cmd, check=False, shell=True, cwd=None, timeout=None) -> CommandRetu stdout, stderr = proc.communicate(timeout=timeout) except subprocess.TimeoutExpired: proc.kill() + + # Sometimes stdout/stderr are passed on to children, in which case killing + # the parent won't close them and communicate will still hang. + proc.stdout.close() + proc.stderr.close() + stdout, stderr = proc.communicate() # Log the message with one call so that multiple statuses From fd77b79a4cc3cf69d8626138d8d5cd539c9e6170 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 13:16:34 +0000 Subject: [PATCH 103/464] test: fix assertions in test_pause_resume We asserted twice that the guest is not responsive anymore after pausing, and zero times that it is responsive again after resuming. Fix this by doing each once. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_pause_resume.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/integration_tests/functional/test_pause_resume.py b/tests/integration_tests/functional/test_pause_resume.py index 3d0ac124c11..4b15c86ddfc 100644 --- a/tests/integration_tests/functional/test_pause_resume.py +++ b/tests/integration_tests/functional/test_pause_resume.py @@ -59,10 +59,6 @@ def test_pause_resume(uvm_nano): # guest or host side were handled. verify_net_emulation_paused(microvm.flush_metrics()) - # Verify guest is no longer active. - with pytest.raises(ChildProcessError): - microvm.ssh.check_output("true") - # Pausing the microVM when it is already `Paused` is allowed # (microVM remains in `Paused` state). microvm.api.vm.patch(state="Paused") @@ -71,6 +67,7 @@ def test_pause_resume(uvm_nano): microvm.api.vm.patch(state="Resumed") # Verify guest is active again. + microvm.ssh.check_output("true") # Resuming the microVM when it is already `Resumed` is allowed # (microVM remains in the running state). From b99abe1bd7a9e8b9b80df0b9ea8197849c6dabf0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:03:13 +0000 Subject: [PATCH 104/464] test: remove timeout from test_high_ingress_traffic It's a fairly tight timeout, and I was hitting it quite frequently while running functional tests with high parallelism. I don't really see any reason why we should be concerned about this specific command simply hitting the pytest timeout when things go wrong, so let's just remove the timeout. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 2072d015ca2..efccd946c61 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -41,9 +41,9 @@ def test_high_ingress_traffic(uvm_plain_any): time.sleep(1) # Start iperf3 client on the host. Send 1Gbps UDP traffic. - # If the net device breaks, iperf will freeze. We have to use a timeout. + # If the net device breaks, iperf will freeze, and we'll hit the pytest timeout utils.check_output( - "timeout 31 {} {} -c {} -u -V -b 1000000000 -t 30".format( + "{} {} -c {} -u -V -b 1000000000 -t 30".format( test_microvm.netns.cmd_prefix(), IPERF_BINARY_HOST, guest_ip, From 36448e94ebf43f04fc55dac5aa2fae6f9132bfea Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:04:58 +0000 Subject: [PATCH 105/464] test: set default timeout of 100s for ssh commands Opportunistically set a 100s timeout. We don't have anything that should run this long, and by manually setting a timeout we avoid hitting the pytest timeout of 300s in case something _does_ go wrong (and hitting the pytest timeout gives significantly less debug information, so a manual timeout is preferred). Signed-off-by: Patrick Roy --- tests/host_tools/network.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index 7877b914d28..4a961e025df 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -109,9 +109,9 @@ def _init_connection(self): We'll keep trying to execute a remote command that can't fail (`/bin/true`), until we get a successful (0) exit code. """ - self.check_output("true", timeout=100, debug=True) + self.check_output("true", debug=True) - def run(self, cmd_string, timeout=None, *, check=False, debug=False): + def run(self, cmd_string, timeout=100, *, check=False, debug=False): """ Execute the command passed as a string in the ssh context. @@ -124,11 +124,11 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False): return self._exec(command, timeout, check=check) - def check_output(self, cmd_string, timeout=None, *, debug=False): + def check_output(self, cmd_string, timeout=100, *, debug=False): """Same as `run`, but raises an exception on non-zero return code of remote command""" return self.run(cmd_string, timeout, check=True, debug=debug) - def _exec(self, cmd, timeout=None, check=False): + def _exec(self, cmd, timeout=100, check=False): """Private function that handles the ssh client invocation.""" if self.netns is not None: cmd = ["ip", "netns", "exec", self.netns] + cmd From 030c2262c30a6e65a4fd9bc3fb42a6ae541853b7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 14:44:31 +0000 Subject: [PATCH 106/464] test: simplify make_guest_dirty_memory Remove the logging from this function, because SSHConnection._exec already does this. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_balloon.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index 2c59fd2e814..41a790190de 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -62,18 +62,10 @@ def lower_ssh_oom_chance(ssh_connection): def make_guest_dirty_memory(ssh_connection, amount_mib=32): """Tell the guest, over ssh, to dirty `amount` pages of memory.""" - logger = logging.getLogger("make_guest_dirty_memory") - lower_ssh_oom_chance(ssh_connection) - cmd = f"/usr/local/bin/fillmem {amount_mib}" try: - exit_code, stdout, stderr = ssh_connection.run(cmd, timeout=1.0) - # add something to the logs for troubleshooting - if exit_code != 0: - logger.error("while running: %s", cmd) - logger.error("stdout: %s", stdout) - logger.error("stderr: %s", stderr) + _ = ssh_connection.run(f"/usr/local/bin/fillmem {amount_mib}", timeout=1.0) except TimeoutExpired: # It's ok if this expires. Sometimes the SSH connection # gets killed by the OOM killer *after* the fillmem program From 3b2c2d4d69f41c99aecb2de10d8c04d6efc26bc9 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 10:57:35 +0000 Subject: [PATCH 107/464] test: use single SSH connection for lifetime of microvm Instead of creating new SSH connections every time we want to run a command inside the microvm, open a single daemonized ssh connection in the constructor of `SSHConnection`, and reuse it until we kill the microvm. Realize this using openssh's ControlMaster/ControlPersist functionality, which allows us to persist the first connection opened to a microvm and multiplex all subsequent commands over this one connection. We need some slight changes in test_pause_restore.py and test_net.py. In the former, since we no longer reconnect to the VM on every ssh command, we will now observe a timeout instead of a connection failure. For the latter, it turns out that @lru_cache treats .ssh_iface() and .ssh_iface(0) as distinct invokations, despire the iface_idx argument of ssh_iface defaulting to 0 (meaning they are actually the same function call). This caused a re-intialization of the SSHConnection object, which then triggered the assertion in _init_connection about the socket file not existing. Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 11 +- tests/host_tools/network.py | 123 ++++++++++++------ .../integration_tests/functional/test_net.py | 7 +- .../functional/test_pause_resume.py | 5 +- 4 files changed, 96 insertions(+), 50 deletions(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index eb755ffc5fa..11fecf720a7 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -247,6 +247,8 @@ def __init__( self.mem_size_bytes = None self.cpu_template_name = None + self._connections = [] + self._pre_cmd = [] if numa_node: node_str = str(numa_node) @@ -282,6 +284,10 @@ def kill(self): for monitor in self.monitors: monitor.stop() + # Kill all background SSH connections + for connection in self._connections: + connection.close() + # We start with vhost-user backends, # because if we stop Firecracker first, the backend will want # to exit as well and this will cause a race condition. @@ -1007,13 +1013,16 @@ def ssh_iface(self, iface_idx=0): """Return a cached SSH connection on a given interface id.""" guest_ip = list(self.iface.values())[iface_idx]["iface"].guest_ip self.ssh_key = Path(self.ssh_key) - return net_tools.SSHConnection( + connection = net_tools.SSHConnection( netns=self.netns.id, ssh_key=self.ssh_key, user="root", host=guest_ip, + control_path=Path(self.chroot()) / f"ssh-{iface_idx}.sock", on_error=self._dump_debug_information, ) + self._connections.append(connection) + return connection @property def ssh(self): diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index 4a961e025df..ff6e58be2b9 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -3,30 +3,35 @@ """Utilities for test host microVM network setup.""" import ipaddress +import os import random +import re +import signal import string -import subprocess from dataclasses import dataclass, field from pathlib import Path -from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_fixed +from tenacity import retry, stop_after_attempt, wait_fixed from framework import utils +from framework.utils import Timeout class SSHConnection: """ SSHConnection encapsulates functionality for microVM SSH interaction. - This class should be instantiated as part of the ssh fixture with the + This class should be instantiated as part of the ssh fixture with the hostname obtained from the MAC address, the username for logging into the image and the path of the ssh key. - This translates into an SSH connection as follows: - ssh -i ssh_key_path username@hostname + Establishes a ControlMaster upon construction, which is then re-used + for all subsequent SSH interactions. """ - def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): + def __init__( + self, netns, ssh_key: Path, control_path: Path, host, user, *, on_error=None + ): """Instantiate a SSH client and connect to a microVM.""" self.netns = netns self.ssh_key = ssh_key @@ -37,22 +42,13 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None): assert (ssh_key.stat().st_mode & 0o777) == 0o400 self.host = host self.user = user + self._control_path = control_path self._on_error = None self.options = [ "-o", - "LogLevel=ERROR", - "-o", - "ConnectTimeout=1", - "-o", - "StrictHostKeyChecking=no", - "-o", - "UserKnownHostsFile=/dev/null", - "-o", - "PreferredAuthentications=publickey", - "-i", - str(self.ssh_key), + f"ControlPath={self._control_path}", ] # _init_connection loops until it can connect to the guest @@ -96,20 +92,82 @@ def scp_get(self, remote_path, local_path, recursive=False): self._scp(self.remote_path(remote_path), local_path, opts) @retry( - retry=retry_if_exception_type(ChildProcessError), - wait=wait_fixed(0.5), + wait=wait_fixed(1), stop=stop_after_attempt(20), reraise=True, ) def _init_connection(self): - """Create an initial SSH client connection (retry until it works). + """Initialize the persistent background connection which will be used + to execute all commands sent via this `SSHConnection` object. Since we're connecting to a microVM we just started, we'll probably have to wait for it to boot up and start the SSH server. We'll keep trying to execute a remote command that can't fail (`/bin/true`), until we get a successful (0) exit code. """ - self.check_output("true", debug=True) + assert not self._control_path.exists() + + # Sadly, we cannot get debug output from this command (e.g. `-vvv`), + # because passing -vvv causes the daemonized ssh to hold on to stderr, + # and inside utils.run_cmd we're using subprocess.communicate, which + # only returns once stderr gets closed (which would thus result in an + # indefinite hang). + establish_cmd = [ + "ssh", + # Only need to pass the ssh key here, as all multiplexed + # connections won't have to re-authenticate + "-i", + str(self.ssh_key), + "-o", + "StrictHostKeyChecking=no", + "-o", + "ConnectTimeout=2", + # Set up a persistent background connection + "-o", + "ControlMaster=auto", + "-o", + "ControlPersist=yes", + *self.options, + self.user_host, + "/usr/bin/true", + ] + + # don't set a low timeout here, because otherwise we might get into a race condition + # where ssh already forked off the persisted connection daemon, but gets killed here + # before exiting itself. In that case, self._control_path will exist, and the retry + # will hit the assert at the start of this function. + self._exec(establish_cmd, check=True) + + def _check_liveness(self) -> int: + """Checks whether the ControlPersist connection is still alive""" + check_cmd = ["ssh", "-O", "check", *self.options, self.user_host] + + _, _, stderr = self._exec(check_cmd, check=True) + + pid_match = re.match(r"Master running \(pid=(\d+)\)", stderr) + + assert pid_match, f"SSH ControlMaster connection not alive anymore: {stderr}" + + return int(pid_match.group(1)) + + def close(self): + """Closes the ControlPersist connection""" + master_pid = self._check_liveness() + + stop_cmd = ["ssh", "-O", "stop", *self.options, self.user_host] + + _, _, stderr = self._exec(stop_cmd, check=True) + + assert "Stop listening request sent" in stderr + + try: + with Timeout(5): + utils.wait_process_termination(master_pid) + except TimeoutError: + # for some reason it won't exit, let's force it... + # if this also fails, when during teardown we'll get an error about + # "found a process with supposedly dead Firecracker's jailer ID" + os.kill(master_pid, signal.SIGKILL) def run(self, cmd_string, timeout=100, *, check=False, debug=False): """ @@ -117,6 +175,8 @@ def run(self, cmd_string, timeout=100, *, check=False, debug=False): If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr. """ + self._check_liveness() + command = ["ssh", *self.options, self.user_host, cmd_string] if debug: @@ -141,27 +201,6 @@ def _exec(self, cmd, timeout=100, check=False): raise - # pylint:disable=invalid-name - def Popen( - self, - cmd: str, - stdin=subprocess.DEVNULL, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - **kwargs, - ) -> subprocess.Popen: - """Execute the command in the guest and return a Popen object. - - pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done") - pop.stdout.read(16) - """ - cmd = ["ssh", *self.options, self.user_host, cmd] - if self.netns is not None: - cmd = ["ip", "netns", "exec", self.netns] + cmd - return subprocess.Popen( - cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs - ) - def mac_from_ip(ip_address): """Create a MAC address based on the provided IP. diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index efccd946c61..7b784e453c5 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -112,11 +112,8 @@ def test_tap_offload(uvm_any): ) # Try to send a UDP message from host with UDP offload enabled - cmd = f"ip netns exec {vm.ssh_iface().netns} python3 ./host_tools/udp_offload.py {vm.ssh_iface().host} {port}" - ret = utils.run_cmd(cmd) - - # Check that the transmission was successful - assert ret.returncode == 0, f"{ret.stdout=} {ret.stderr=}" + cmd = f"ip netns exec {vm.ssh.netns} python3 ./host_tools/udp_offload.py {vm.ssh.host} {port}" + utils.check_output(cmd) # Check that the server received the message ret = vm.ssh.run(f"cat {out_filename}") diff --git a/tests/integration_tests/functional/test_pause_resume.py b/tests/integration_tests/functional/test_pause_resume.py index 4b15c86ddfc..34b9a9a7229 100644 --- a/tests/integration_tests/functional/test_pause_resume.py +++ b/tests/integration_tests/functional/test_pause_resume.py @@ -4,6 +4,7 @@ import platform import time +from subprocess import TimeoutExpired import pytest @@ -52,8 +53,8 @@ def test_pause_resume(uvm_nano): microvm.flush_metrics() # Verify guest is no longer active. - with pytest.raises(ChildProcessError): - microvm.ssh.check_output("true") + with pytest.raises(TimeoutExpired): + microvm.ssh.check_output("true", timeout=1) # Verify emulation was indeed paused and no events from either # guest or host side were handled. From 9455ed0420bcd4a7a9ea0f40662ee2d7c2195fb1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 15:51:02 +0000 Subject: [PATCH 108/464] poetry: remove fabric and netns dependencies With the ControlMaster/ControlPersist approach, these are no needed anymore. I'm not reverting the commit that added them because that also contained an update of poetry.lock. I'm also not rebuilding the devctr for this because the dependencies will simply be dropped the next time we're rebuilding it. Signed-off-by: Patrick Roy --- tools/devctr/poetry.lock | 360 +----------------------------------- tools/devctr/pyproject.toml | 2 - 2 files changed, 1 insertion(+), 361 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index eb969e9eda2..b04d05efac9 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -210,44 +210,6 @@ files = [ [package.dependencies] aiohttp = "*" -[[package]] -name = "bcrypt" -version = "4.2.1" -description = "Modern password hashing for your software and your servers" -optional = false -python-versions = ">=3.7" -files = [ - {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, - {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, - {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, - {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, - {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, - {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, - {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, - {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, - {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, - {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, - {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, - {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, - {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, -] - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - [[package]] name = "black" version = "24.10.0" @@ -305,85 +267,6 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - [[package]] name = "charset-normalizer" version = "3.4.0" @@ -523,57 +406,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "cryptography" -version = "44.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - [[package]] name = "decorator" version = "5.1.1" @@ -585,23 +417,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "deprecated" -version = "1.2.15" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, - {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] - [[package]] name = "dill" version = "0.3.9" @@ -659,26 +474,6 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] -[[package]] -name = "fabric" -version = "3.2.2" -description = "High level SSH command execution" -optional = false -python-versions = "*" -files = [ - {file = "fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"}, - {file = "fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"}, -] - -[package.dependencies] -decorator = ">=5" -deprecated = ">=1.2" -invoke = ">=2.0" -paramiko = ">=2.4" - -[package.extras] -pytest = ["pytest (>=7)"] - [[package]] name = "filelock" version = "3.16.1" @@ -863,17 +658,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "invoke" -version = "2.2.0" -description = "Pythonic task execution" -optional = false -python-versions = ">=3.6" -files = [ - {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, - {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, -] - [[package]] name = "ipython" version = "8.30.0" @@ -1347,16 +1131,6 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[[package]] -name = "netns" -version = "1.0" -description = "Wrapper for the Linux setns() system call" -optional = false -python-versions = "*" -files = [ - {file = "netns-1.0.tar.gz", hash = "sha256:dc994c53e415baa739072784292630724d609566fb4a60ed8feef38dd9ecdca5"}, -] - [[package]] name = "numpy" version = "2.2.0" @@ -1465,27 +1239,6 @@ files = [ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] -[[package]] -name = "paramiko" -version = "3.5.0" -description = "SSH2 protocol library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, - {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, -] - -[package.dependencies] -bcrypt = ">=3.2" -cryptography = ">=3.3" -pynacl = ">=1.5" - -[package.extras] -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -invoke = ["invoke (>=2.0)"] - [[package]] name = "parso" version = "0.8.4" @@ -1728,17 +1481,6 @@ files = [ [package.extras] tests = ["pytest"] -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - [[package]] name = "pygments" version = "2.18.0" @@ -1782,32 +1524,6 @@ tomlkit = ">=0.10.1" spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - [[package]] name = "pytest" version = "8.3.4" @@ -2565,80 +2281,6 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] -[[package]] -name = "wrapt" -version = "1.17.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.8" -files = [ - {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, - {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, - {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, - {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, - {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, - {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, - {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, - {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, - {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, - {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, - {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, - {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, - {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, - {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, - {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, - {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, - {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, - {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, - {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, - {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, - {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, - {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, - {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, - {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, - {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, - {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, - {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, - {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, - {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, - {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, - {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, - {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, - {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, - {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, - {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, - {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, - {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, -] - [[package]] name = "yarl" version = "1.18.3" @@ -2738,4 +2380,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "c3b6e2c1d9a0a7926b61ca38f9e91fd1c1c0519a1703d6eaa0fd07fcf5898cbd" +content-hash = "e38bfcb8811fb9b774956ed4b0e82603dbe5b66d8cb5bc4af6ed86417a9d5d1d" diff --git a/tools/devctr/pyproject.toml b/tools/devctr/pyproject.toml index 188a3b315bd..a4f7178aa5d 100644 --- a/tools/devctr/pyproject.toml +++ b/tools/devctr/pyproject.toml @@ -10,7 +10,6 @@ aws-embedded-metrics = "^3.1.0" black = "^24.3.0" # Gitlint locks this to 8.1.3. Lock from our side too to prevent different versions click = "8.1.3" -fabric = "^3.2.2" filelock = "^3.13.4" gitlint = "^0.19.1" ipython = "^8.15.0" @@ -19,7 +18,6 @@ mdformat = "^0.7.17" mdformat-gfm = "^0.3.5" mdformat-footnote = "^0.1.1" mdformat-frontmatter = "^2.0.8" -netns = "^1.0.0" openapi-spec-validator = "^0.7.1" psutil = "^6.0.0" pylint = "^3" From 8c7ee82f9d603faa6776671024ca7258c8e28d19 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 16:08:50 +0000 Subject: [PATCH 109/464] fix: properly clean up tmp dir after shared build Building the A/B binaries happens in a tmpdir, which we try to delete at the end. But we create files in the tmpdir from a privileged docker container, so to delete this tmpdir we also need elevated privileges Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 3b4d89ec392..7d41229b2e7 100755 --- a/tools/devtool +++ b/tools/devtool @@ -525,7 +525,7 @@ cmd_build() { git branch -D $branch_name mkdir -p build/"$revision" cp $tmp_dir/build/cargo_target/$(uname -m)-unknown-linux-$libc/$profile/* build/"$revision" - rm -rf $tmp_dir + cmd_sh "rm -rf $tmp_dir" fi return $ret From 0b4266b0f3112e949bb4bf6eb5425c2d8ff097cb Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 08:12:11 +0000 Subject: [PATCH 110/464] fix(test): remove timeouts from MSR integration tests These run in a nightly pipeline and apparently the read/write MSR scripts take longer than the 100s default timeout added in b99abe1. Fixes: 36448e94ebf4 ("test: set default timeout of 100s for ssh commands") Signed-off-by: Patrick Roy --- .../functional/test_cpu_features_x86_64.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 1af6a39f83a..dce36254cb6 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -314,7 +314,7 @@ def test_cpu_rdmsr( ) vm.start() vm.ssh.scp_put(DATA_FILES / "msr_reader.sh", "/tmp/msr_reader.sh") - _, stdout, stderr = vm.ssh.run("/tmp/msr_reader.sh") + _, stdout, stderr = vm.ssh.run("/tmp/msr_reader.sh", timeout=None) assert stderr == "" # Load results read from the microvm @@ -362,7 +362,9 @@ def dump_msr_state_to_file(dump_fname, ssh_conn, shared_names): ssh_conn.scp_put( shared_names["msr_reader_host_fname"], shared_names["msr_reader_guest_fname"] ) - _, stdout, stderr = ssh_conn.run(shared_names["msr_reader_guest_fname"]) + _, stdout, stderr = ssh_conn.run( + shared_names["msr_reader_guest_fname"], timeout=None + ) assert stderr == "" with open(dump_fname, "w", encoding="UTF-8") as file: @@ -416,7 +418,9 @@ def test_cpu_wrmsr_snapshot(microvm_factory, guest_kernel, rootfs, msr_cpu_templ wrmsr_input_guest_fname = "/tmp/wrmsr_input.txt" vm.ssh.scp_put(wrmsr_input_host_fname, wrmsr_input_guest_fname) - _, _, stderr = vm.ssh.run(f"{msr_writer_guest_fname} {wrmsr_input_guest_fname}") + _, _, stderr = vm.ssh.run( + f"{msr_writer_guest_fname} {wrmsr_input_guest_fname}", timeout=None + ) assert stderr == "" # Dump MSR state to a file that will be published to S3 for the 2nd part of the test From e56b6a2f109e036d31966cde0f0f963e4ac5172c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 08:25:16 +0000 Subject: [PATCH 111/464] gitlint: ignore "Fixes" lines Since these repeat commit titles, they can get longer than the configured body line length. So just ignore them. Signed-off-by: Patrick Roy --- .gitlint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlint b/.gitlint index 8840b19bfe8..3b0cc0e07a0 100644 --- a/.gitlint +++ b/.gitlint @@ -9,8 +9,8 @@ line-length=72 [ignore-body-lines] # Ignore HTTP reference links -# Ignore lines that start with 'Co-Authored-By' or with 'Signed-off-by' -regex=(^\[.+\]: http.+)|(^Co-Authored-By)|(^Signed-off-by) +# Ignore lines that start with 'Co-Authored-By', with 'Signed-off-by' or with 'Fixes' +regex=(^\[.+\]: http.+)|(^Co-Authored-By)|(^Signed-off-by)|(^Fixes:) [ignore-by-author-name] # Ignore certain rules for commits of which the author name matches a regex From e7ccf54e7ca8997b8d4be9f9f2240aea10046ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 12 Dec 2024 15:20:43 +0100 Subject: [PATCH 112/464] tests: compile test_syscall with musl-gcc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition do a few more cleanups to the test: - Use `atol` to read longs - musl makes an ioctl that is not permitted in seccomp. We didn't use the return code anyway, so remove it. Signed-off-by: Pablo Barbáchano --- tests/host_tools/test_syscalls.c | 13 ++++++------- .../security/test_seccomp_validate.py | 16 ++++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/host_tools/test_syscalls.c b/tests/host_tools/test_syscalls.c index 6a58edf0983..685e45acde0 100644 --- a/tests/host_tools/test_syscalls.c +++ b/tests/host_tools/test_syscalls.c @@ -28,7 +28,6 @@ void install_bpf_filter(char *bpf_file) { exit(EXIT_FAILURE); } size_t size = sb.st_size; - size_t insn_len = size / sizeof(struct sock_filter); struct sock_filter *filterbuf = (struct sock_filter*)malloc(size); if (read(fd, filterbuf, size) == -1) { perror("read"); @@ -36,6 +35,7 @@ void install_bpf_filter(char *bpf_file) { } /* Install seccomp filter */ + size_t insn_len = size / sizeof(struct sock_filter); struct sock_fprog prog = { .len = (unsigned short)(insn_len), .filter = filterbuf, @@ -60,11 +60,11 @@ int main(int argc, char **argv) { char *bpf_file = argv[1]; long syscall_id = atoi(argv[2]); long arg0, arg1, arg2, arg3; - arg0 = arg1 = arg2 = arg3 = 0; - if (argc > 3) arg0 = atoi(argv[3]); - if (argc > 4) arg1 = atoi(argv[4]); - if (argc > 5) arg2 = atoi(argv[5]); - if (argc > 6) arg3 = atoi(argv[6]); + arg0 = arg1 = arg2 = arg3 = 0L; + if (argc > 3) arg0 = atol(argv[3]); + if (argc > 4) arg1 = atol(argv[4]); + if (argc > 5) arg2 = atol(argv[5]); + if (argc > 6) arg3 = atol(argv[6]); /* read seccomp filter from file */ if (strcmp(bpf_file, "/dev/null") != 0) { @@ -72,6 +72,5 @@ int main(int argc, char **argv) { } long res = syscall(syscall_id, arg0, arg1, arg2, arg3); - printf("%ld\n", res); return EXIT_SUCCESS; } diff --git a/tests/integration_tests/security/test_seccomp_validate.py b/tests/integration_tests/security/test_seccomp_validate.py index 5a0be067899..b91c7590a2b 100644 --- a/tests/integration_tests/security/test_seccomp_validate.py +++ b/tests/integration_tests/security/test_seccomp_validate.py @@ -13,18 +13,18 @@ import seccomp from framework import utils -from host_tools import cargo_build ARCH = platform.machine() -@pytest.fixture(scope="session") -def bin_test_syscall(test_fc_session_root_path): +@pytest.fixture +def bin_test_syscall(tmp_path): """Build the test_syscall binary.""" - test_syscall_bin = Path(test_fc_session_root_path) / "test_syscall" - cargo_build.gcc_compile("host_tools/test_syscalls.c", test_syscall_bin) + test_syscall_bin = tmp_path / "test_syscall" + compile_cmd = f"musl-gcc -static host_tools/test_syscalls.c -o {test_syscall_bin}" + utils.check_output(compile_cmd) assert test_syscall_bin.exists() - yield test_syscall_bin + yield test_syscall_bin.resolve() class BpfMapReader: @@ -77,11 +77,11 @@ def split(self): for _ in range(map_len): # read key key_str_len = self.read_format(" Date: Fri, 13 Dec 2024 11:15:53 +0000 Subject: [PATCH 113/464] fix(test): ensure socat gets killed in test_5_snapshots Use a try-finally block inside check_guest_connection to make sure that socat gets killed even if something inside check_guest_connection fails and raises an exception. Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 96 +++++++++++++++++----------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index 3f6885e3afd..fe192e92f06 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -142,53 +142,55 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): ["socat", f"UNIX-LISTEN:{server_port_path},fork,backlog=5", "exec:'/bin/cat'"] ) - # Link the listening Unix socket into the VM's jail, so that - # Firecracker can connect to it. - attempt = 0 - # But 1st, give socat a bit of time to create the socket - while not Path(server_port_path).exists() and attempt < 3: - time.sleep(0.2) - attempt += 1 - vm.create_jailed_resource(server_port_path) - - # Increase maximum process count for the ssh service. - # Avoids: "bash: fork: retry: Resource temporarily unavailable" - # Needed to execute the bash script that tests for concurrent - # vsock guest initiated connections. - pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" - ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") - assert ecode == 0, "Unable to set max process count for guest ssh service." - - # Build the guest worker sub-command. - # `vsock_helper` will read the blob file from STDIN and send the echo - # server response to STDOUT. This response is then hashed, and the - # hash is compared against `blob_hash` (computed on the host). This - # comparison sets the exit status of the worker command. - worker_cmd = "hash=$(" - worker_cmd += "cat {}".format(blob_path) - worker_cmd += " | /tmp/vsock_helper echo 2 {}".format(ECHO_SERVER_PORT) - worker_cmd += " | md5sum | cut -f1 -d\\ " - worker_cmd += ")" - worker_cmd += ' && [[ "$hash" = "{}" ]]'.format(blob_hash) - - # Run `TEST_CONNECTION_COUNT` concurrent workers, using the above - # worker sub-command. - # If any worker fails, this command will fail. If all worker sub-commands - # succeed, this will also succeed. - cmd = 'workers="";' - cmd += "for i in $(seq 1 {}); do".format(TEST_CONNECTION_COUNT) - cmd += " ({})& ".format(worker_cmd) - cmd += ' workers="$workers $!";' - cmd += "done;" - cmd += "for w in $workers; do wait $w || (wait; exit 1); done" - - ecode, _, stderr = vm.ssh.run(cmd) - echo_server.terminate() - rc = echo_server.wait() - # socat exits with 128 + 15 (SIGTERM) - assert rc == 143 - - assert ecode == 0, stderr + try: + # Link the listening Unix socket into the VM's jail, so that + # Firecracker can connect to it. + attempt = 0 + # But 1st, give socat a bit of time to create the socket + while not Path(server_port_path).exists() and attempt < 3: + time.sleep(0.2) + attempt += 1 + vm.create_jailed_resource(server_port_path) + + # Increase maximum process count for the ssh service. + # Avoids: "bash: fork: retry: Resource temporarily unavailable" + # Needed to execute the bash script that tests for concurrent + # vsock guest initiated connections. + pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" + ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") + assert ecode == 0, "Unable to set max process count for guest ssh service." + + # Build the guest worker sub-command. + # `vsock_helper` will read the blob file from STDIN and send the echo + # server response to STDOUT. This response is then hashed, and the + # hash is compared against `blob_hash` (computed on the host). This + # comparison sets the exit status of the worker command. + worker_cmd = "hash=$(" + worker_cmd += "cat {}".format(blob_path) + worker_cmd += " | /tmp/vsock_helper echo 2 {}".format(ECHO_SERVER_PORT) + worker_cmd += " | md5sum | cut -f1 -d\\ " + worker_cmd += ")" + worker_cmd += ' && [[ "$hash" = "{}" ]]'.format(blob_hash) + + # Run `TEST_CONNECTION_COUNT` concurrent workers, using the above + # worker sub-command. + # If any worker fails, this command will fail. If all worker sub-commands + # succeed, this will also succeed. + cmd = 'workers="";' + cmd += "for i in $(seq 1 {}); do".format(TEST_CONNECTION_COUNT) + cmd += " ({})& ".format(worker_cmd) + cmd += ' workers="$workers $!";' + cmd += "done;" + cmd += "for w in $workers; do wait $w || (wait; exit 1); done" + + ecode, _, stderr = vm.ssh.run(cmd) + + assert ecode == 0, stderr + finally: + echo_server.terminate() + rc = echo_server.wait() + # socat exits with 128 + 15 (SIGTERM) + assert rc == 143 def make_host_port_path(uds_path, port): From 130af91a280d6a26db16893e18106a215be8799e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 11:18:15 +0000 Subject: [PATCH 114/464] refactor(test): Use check_output in check_guest_connections Now that the assertion on the `run` return code is paired with the .run call itself, combine them into .check_output. Also use check_output further up. Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index fe192e92f06..244850c3496 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -156,9 +156,9 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): # Avoids: "bash: fork: retry: Resource temporarily unavailable" # Needed to execute the bash script that tests for concurrent # vsock guest initiated connections. - pids_max_file = "/sys/fs/cgroup/system.slice/ssh.service/pids.max" - ecode, _, _ = vm.ssh.run(f"echo 1024 > {pids_max_file}") - assert ecode == 0, "Unable to set max process count for guest ssh service." + vm.ssh.check_output( + "echo 1024 > /sys/fs/cgroup/system.slice/ssh.service/pids.max" + ) # Build the guest worker sub-command. # `vsock_helper` will read the blob file from STDIN and send the echo @@ -183,9 +183,7 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): cmd += "done;" cmd += "for w in $workers; do wait $w || (wait; exit 1); done" - ecode, _, stderr = vm.ssh.run(cmd) - - assert ecode == 0, stderr + vm.ssh.check_output(cmd) finally: echo_server.terminate() rc = echo_server.wait() From 77d3704f847d3ef32a33a0c18b330fb5e2534cb1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 13 Dec 2024 11:23:15 +0000 Subject: [PATCH 115/464] refactor(test): improve retry look in check_guest_connections Use `tenancy.Retrying` instead of the home-grown retry loop. This has the advantage that we don't simply give up after 3 attempts, but instead raise a meaningful error message (whereas before I guess we would just fail further down the function when trying to do something that assumes the file exists). Signed-off-by: Patrick Roy --- tests/framework/utils_vsock.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/framework/utils_vsock.py b/tests/framework/utils_vsock.py index 244850c3496..9561c1c26f2 100644 --- a/tests/framework/utils_vsock.py +++ b/tests/framework/utils_vsock.py @@ -11,6 +11,8 @@ from subprocess import Popen from threading import Thread +from tenacity import Retrying, stop_after_attempt, wait_fixed + ECHO_SERVER_PORT = 5252 SERVER_ACCEPT_BACKLOG = 128 TEST_CONNECTION_COUNT = 50 @@ -143,13 +145,17 @@ def check_guest_connections(vm, server_port_path, blob_path, blob_hash): ) try: + # Give socat a bit of time to create the socket + for attempt in Retrying( + wait=wait_fixed(0.2), + stop=stop_after_attempt(3), + reraise=True, + ): + with attempt: + assert Path(server_port_path).exists() + # Link the listening Unix socket into the VM's jail, so that # Firecracker can connect to it. - attempt = 0 - # But 1st, give socat a bit of time to create the socket - while not Path(server_port_path).exists() and attempt < 3: - time.sleep(0.2) - attempt += 1 vm.create_jailed_resource(server_port_path) # Increase maximum process count for the ssh service. From a8a240b8712396afc2f5c220ed32a1ec29b78267 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 15:42:01 +0000 Subject: [PATCH 116/464] test: add support for running commands with nightly toolchain Add a `nightly` flag to the `cargo` function, which causes the requested command to be executing using the nightly toolchain. We have a nightly toolchain in our container due to kani. But since the toolchain version is prescribed by kani, we need to dynamically determine its name from `rustup toolchain list`, and cannot just use `+nightly`. Signed-off-by: Patrick Roy --- tests/host_tools/cargo_build.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/host_tools/cargo_build.py b/tests/host_tools/cargo_build.py index da72e5433b2..5a029f8c5f4 100644 --- a/tests/host_tools/cargo_build.py +++ b/tests/host_tools/cargo_build.py @@ -14,6 +14,11 @@ DEFAULT_TARGET_DIR = f"{DEFAULT_TARGET}/release/" +def nightly_toolchain() -> str: + """Receives the name of the installed nightly toolchain""" + return utils.check_output("rustup toolchain list | grep nightly").stdout.strip() + + def cargo( subcommand, cargo_args: str = "", @@ -21,11 +26,15 @@ def cargo( *, env: dict = None, cwd: str = None, + nightly: bool = False, ): """Executes the specified cargo subcommand""" + toolchain = f"+{nightly_toolchain()}" if nightly else "" env = env or {} env_string = " ".join(f'{key}="{str(value)}"' for key, value in env.items()) - cmd = f"{env_string} cargo {subcommand} {cargo_args} -- {subcommand_args}" + cmd = ( + f"{env_string} cargo {toolchain} {subcommand} {cargo_args} -- {subcommand_args}" + ) return utils.check_output(cmd, cwd=cwd) From a678ecc7c62e25dc96824365681f801fc8400da3 Mon Sep 17 00:00:00 2001 From: Jonathan Woollett-Light Date: Thu, 12 Oct 2023 10:00:09 +0100 Subject: [PATCH 117/464] ci: Test for unused cargo dependencies From: Jonathan Woollett-Light Adds test for unused cargo dependencies. Signed-off-by: Jonathan Woollett-Light Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- tests/integration_tests/build/test_dependencies.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/integration_tests/build/test_dependencies.py diff --git a/tests/integration_tests/build/test_dependencies.py b/tests/integration_tests/build/test_dependencies.py new file mode 100644 index 00000000000..6ee3a675702 --- /dev/null +++ b/tests/integration_tests/build/test_dependencies.py @@ -0,0 +1,12 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Enforces controls over dependencies.""" + +from host_tools.cargo_build import cargo + + +def test_unused_dependencies(): + """ + Test that there are no unused dependencies. + """ + cargo("udeps", "--all", nightly=True) From 0bee970f8ee344604d5d110a91712d1f1f6559a2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 11 Dec 2024 16:50:43 +0000 Subject: [PATCH 118/464] chore: remove unused dependencies from Cargo.tomls The new test caught these. yay! Signed-off-by: Patrick Roy --- Cargo.lock | 27 +-------------------------- src/jailer/Cargo.toml | 1 - src/utils/Cargo.toml | 7 ------- src/vmm/Cargo.toml | 1 - 4 files changed, 1 insertion(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28561608a6a..8be5eab9cf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,12 +284,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "ciborium" version = "0.2.2" @@ -803,7 +797,6 @@ version = "1.11.0-dev" dependencies = [ "libc", "log-instrument", - "nix 0.29.0", "regex", "thiserror 2.0.6", "utils", @@ -965,18 +958,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -1467,7 +1448,7 @@ dependencies = [ "bitflags 2.6.0", "cfg-if", "libc", - "nix 0.27.1", + "nix", "thiserror 1.0.69", "userfaultfd-sys", ] @@ -1493,15 +1474,10 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "utils" version = "0.1.0" dependencies = [ - "derive_more", "displaydoc", "libc", "log-instrument", - "serde", - "serde_json", "thiserror 2.0.6", - "vm-memory", - "vmm-sys-util", ] [[package]] @@ -1600,7 +1576,6 @@ dependencies = [ "itertools 0.13.0", "kvm-bindings", "kvm-ioctls", - "lazy_static", "libc", "linux-loader", "log", diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index f486944ac3b..c84b09450b0 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -14,7 +14,6 @@ bench = false [dependencies] libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -nix = { version = "0.29.0", default-features = false, features = ["dir"] } regex = { version = "1.11.1", default-features = false, features = ["std"] } thiserror = "2.0.6" vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 923155c265e..dd5652718da 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -9,17 +9,10 @@ license = "Apache-2.0" bench = false [dependencies] -derive_more = { version = "1.0.0", default-features = false, features = ["from"] } displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.6" -vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -vmm-sys-util = "0.12.1" - -[dev-dependencies] -serde_json = "1.0.133" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index ec3137be748..0ab810b6573 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -24,7 +24,6 @@ gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.1" -lazy_static = "1.5.0" libc = "0.2.168" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } From 7121895761908ad8fb54d51260f8dc57ab564bdb Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 22 Nov 2024 07:57:24 +0000 Subject: [PATCH 119/464] Add a test that fails if there are obviously unneeded seccomp rules Since Firecracker uses the musl target, it is statically compiled against all of its dependencies. This means that all syscalls that Firecracker can possibly do, are represented by `syscall`/`svc #0x0` instructions inside its binary. By doing some primitive static analysis, it is possible to determine, for each of these instructions, what the actual syscall number is (the idea being: it will probably be a constant loaded into a specific register, determined by Linux's syscall convention, very near the instruction itself). On a best-effort basis, we can also try to determine the values of all registers that might holds syscall arguments (for things like ioctls, this works very well, because the ioctl number is almost always a constant loaded very closely to the syscall instruction). The static_analysis.py file implements the logic for this analysis. We essentially start at each syscall instruction, and then work through the preceding instructions in reverse order, trying to symbolically execute the program in reverse until we figure out the value of the register that holds the syscall number. Thankfully, because of the above mentioned locally, this means we only need to really understand a handful of instructions (based on the assumption that we can ignore instructions that do not explicitly refer to registers that we care about). For example, on x86_64, the syscall number is stored in the eax register, so if we encounter the following instruction sequence xor %ebx,%ebx mov %ebx,%eax syscall we first symbolically execute the "mov", and determine that to figure out the syscall number, we actually need to determine the value of the ebx register. So we go back one more instruction, and find out that %ebx is explicitly set to 0. Thus, forward propagating this 0 to the syscall instruction again, we find that we're doing a `read` syscall. Things get a bit more complicated on ARM, where we don't have to only care about register-to-register transfers, but also things like `add` instructions. For these, we must also keep a "log" of manipulations to apply during forward propagation. For example, on ARM the syscall number is passed in the w8 register, so in the following sequence mov w19, #0x6 add w8, w19, #0x1 svc #0x0 we determine that to compute the syscall number, we must first determine the value of the w19 register, but also we must remember that when we forward propagate the value 0x6 from the w19 register, we must add 1 to it when propagating into the w8 register. Sometimes, we additionally have to deal with wrapper functions around syscalls (e.g. `libc::syscall`). For these, we need to translate the list of syscall number and syscall arguments that the wrapper received according to to the architectures C calling convention (cdecl on x86_64, w0-w7 for arguments on ARM) into what the wrapper will eventually pass to the syscall instruction. On x86_64 this comes with the complication that cdecl only allows passing 6 arguments in registers, but syscall nr + all arguments are up to 7 values. Thus, when a syscall is invoked via libc::syscall, we can only determine up to 5 syscall arguments (the final one would be on the stack, and stack analysis would significantly complicate this script). Lastly, we sometimes also have wrappers for specific syscalls (e.g. ioctl). Here, we do something very similar to the above, however since now the syscall number is "implicit" (e.g. not an argument to the wrapper function, but rather hard-coded into the wrapper), we no not actually run into problems with argument counts on x86_64. We implement this logic because it allows us to determine more arguments (for example, if we did not explicitly look at callsites of the ioctl wrapper, we would not be able to determine which ioctl numbers are actually invoked, greatly reducing the usefulness, as our seccomp filters are large ioctls). After determining all the syscalls, we then compare it to our seccomp filters. We look at all our allowed rules, and compute the set of rules that does not match _any_ of the actual syscalls invoked by the binary. If any such are found, we fail inside a new integration test. There are fairly big limitations to this approach. Because we're doing a global analysis of the firecracker binary, we cannot differentiate between syscalls on different threads, and also not between syscalls done before and after actual application of seccomp filters. For this, we would need some sort of control flow graph analysis, which is made significantly harder due to the presence of dynamic dispatch. Nevertheless, this simple approach already showed 4 redundant syscall rules (and playing around with applying the script to reduced compilation units showed a lot more unneeded rules for the vcpu thread). For all of this to work, we need to compile Firecracker as a non-position independent executable (to get the compiler to general direct calls with absolute addresses, instead of instruction pointer relative ones). Since all dependencies also need to be compiled this way, we have to use cargo's unstable `-Zbuild-std` feature, which thus means we need a nightly toolchain. Signed-off-by: Patrick Roy --- tests/framework/static_analysis.py | 617 ++++++++++++++++++ .../build/test_seccomp_no_redundant_rules.py | 37 ++ 2 files changed, 654 insertions(+) create mode 100644 tests/framework/static_analysis.py create mode 100644 tests/integration_tests/build/test_seccomp_no_redundant_rules.py diff --git a/tests/framework/static_analysis.py b/tests/framework/static_analysis.py new file mode 100644 index 00000000000..fd249f59b85 --- /dev/null +++ b/tests/framework/static_analysis.py @@ -0,0 +1,617 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Module to perform a static analysis of a binary to determine all +actually invoked syscalls. Compares these against seccomp filters, and lists +redundant rules (e.g. those never triggered because the syscall they allow is not +actually used in the binary).""" + +import functools +import json +import logging +import platform +import re +import subprocess +from abc import ABC, abstractmethod +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path +from typing import Callable, ClassVar, Generic, Tuple, TypeVar, get_args + +import seccomp + +logger = logging.getLogger(__name__) + +# pylint: disable=c-extension-no-member,too-many-return-statements,too-few-public-methods + + +@dataclass +class Instruction(ABC): + """ABC representing a single assembly instruction""" + + mnemonic: str + args: list[str] + + comment_prefix: ClassVar[str] + + @property + @abstractmethod + def is_call(self): + """Checks whether the given instruction is a subroutine call""" + + @property + @abstractmethod + def is_syscall(self): + """Checks whether the given instruction is a syscall instruction""" + + @classmethod + def from_str(cls, insn_str): + """Parses the given string as a single assembly instruction, in the syntax that + objdump uses by default on this architecture""" + # remove comments + insn_str = re.sub(rf"\s+{cls.comment_prefix}.*", "", insn_str) + parts = insn_str.split(maxsplit=1) + args = [] + if len(parts) > 1: + # Strip each argument, in case objdump decides to put , + # spaces after commas (happens on ARM, doesn't happen on x86) + args = [x.strip() for x in parts[1].split(",")] + return cls(parts[0], args) + + @abstractmethod + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + """ + If this instruction loads an immediate into the given register, returns + that immediate as an integer. If the instruction is a register to register transfer, + returns the source register for this transfer. If this instruction doesn't change + the given register, returns the given register. Returns None if we don't know + how to backpropagate through this instruction. + + :param reg: the register to backpropagate through this instruction + :return: An integer if the register is loaded with an immediate by this instruction, or a register + which needs to be backpropagated further (together with an optional forward-propagation + function). + """ + + def __str__(self): + return f"{self.mnemonic} {','.join(self.args)}" + + +class InstructionX86_64(Instruction): # pylint: disable=invalid-name + """A x86_64 instruction""" + + comment_prefix = "#" + + @property + def is_call(self): + return self.mnemonic in ["call", "jmp"] + + @property + def is_syscall(self): + return self.mnemonic == "syscall" + + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + # Simplifying assumption: an instruction will not modify a register + # that it doesn't reference (generally wrong, but fine for our purposes) + affected_registers = [ + match for (match, _) in re.findall(r"(%[a-z0-9]{2,4})(\W|)", str(self)) + ] + if reg not in affected_registers: + return reg + + match self.mnemonic: + case "mov": + if len(self.args) != 2: + raise UnsupportedInstructionError(self, reg) + + src, dst = self.args + + if dst == reg: + # an immediate load + if src.startswith("$"): + return int(src[3:], 16) + # We moved something into our target register. If it's a new register, we understand + # what's going on. Anything else, and tough luck + if re.match(r"^%\w{2,4}$", src): + return src + raise UnsupportedInstructionError(self, reg) + return reg + case "xor": + src, dst = self.args + + if src == dst: + # we know that reg is part of the arguments, and we know that the arguments are identical + # Thus we have xor reg,reg, which is effectively zeroing reg + return 0 + case "push": + # a push doesn't do anything + return reg + + raise UnsupportedInstructionError(self, reg) + + +class InstructionAarch64(Instruction): + """An aarch64 assembly instruction""" + + comment_prefix = "//" + + @property + def is_call(self): + return self.mnemonic in ["b", "bl"] + + @property + def is_syscall(self): + return self.mnemonic == "svc" and self.args == ["#0x0"] + + def backpropagate_register( + self, reg: str + ) -> str | int | Tuple[str, Callable[[int], int]]: + affected_registers = [ + match + for (_, match, _) in re.findall(r"(\s|,)([wx]\d{1,2})(\W|)", str(self)) + ] + if reg not in affected_registers: + return reg + + match self.mnemonic: + case "mov": + if len(self.args) != 2: + raise UnsupportedInstructionError(self, reg) + + dst, src = self.args + + if dst == reg: + # an immediate load + if src.startswith("#"): + return int(src[3:], 16) + + if src in ["xzr", "wzr"]: + # See https://developer.arm.com/documentation/102374/0102/Registers-in-AArch64---other-registers + return 0 + + # We moved something into our target register. If it's a new register, we understand + # what's going on. Anything else, and tough luck + if re.match(r"^[xw]\d{1,2}$", src): + return src + + raise UnsupportedInstructionError(self, reg) + return reg + case "movk": + # https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/MOVK + assert len(self.args) in [2, 3], str(self) + + immediate = int(self.args[1][3:], 16) + shift = 0 + if len(self.args) == 3: + # shift has form "lsl #", so strip first 5 characters + shift = int(self.args[2][5:]) + + mask = 0b1111_1111_1111_1111 << shift + + return reg, lambda x: (x & ~mask) | (immediate << shift) + case "add" | "sub": + if len(self.args) != 3: + raise UnsupportedInstructionError(self, reg) + + dst, src, imm = self.args + + if dst != reg: + return reg + + try: + # We can only handle additions of constants, because + # the backpropagation algorithm cannot follow multiple registers. + imm = int(imm[3:], 16) + except ValueError as exc: + raise UnsupportedInstructionError(self, reg) from exc + + if self.mnemonic == "add": + return src, lambda x: x + imm + # must have self.mnemonic == "sub" here by the case label above. + return src, lambda x: x - imm + + raise UnsupportedInstructionError(self, reg) + + +TInstruction = TypeVar( # pylint: disable=invalid-name + "TInstruction", bound=Instruction +) + + +class Architecture(Generic[TInstruction]): + """ABC representing an instruction set architecture, specifically containing information + pertaining to syscall and subroutine call conventions""" + + # The symbolic name of the register used to pass the syscall number to the architectures + # syscall instruction + syscall_nr_register: ClassVar[str] + + # The list of registers (in order) used to pass arguments to the architectures syscall instruction + syscall_argument_registers: ClassVar[list[str]] + + # The list of registers (in order) used to pass arguments to normal function calls + fn_call_argument_registers: ClassVar[list[str]] + + # Convert to the correct variant of seccomp's Arch enum + seccomp_arch: ClassVar[seccomp.Arch] + + t_instruction: type + + def __init_subclass__(cls) -> None: + # Determine the generic parameter of a subclass, and store it in t_instruction. pylint doesnt understand it + # pylint: disable=no-member + cls.t_instruction = get_args(cls.__orig_bases__[0])[0] + + @staticmethod + @abstractmethod + def generalize_reg(reg: str) -> list[str]: + """For a given register, return a list of registers that partially alias it. + + E.g. on x86, when given %rdi as input, return [%rdi, %edi, %di]""" + + @classmethod + def determine_register_value(cls, instructions: list[TInstruction], register: str): + """Determines the value of the given register at the end of the given instruction sequence + via backpropagation""" + looking_for = cls.generalize_reg(register) + transforms = [] + + for insn in reversed(instructions): + for reg in looking_for: + next_reg = insn.backpropagate_register(reg) + + if isinstance(next_reg, tuple): + next_reg, transform = next_reg + + transforms.insert(0, transform) + + if isinstance(next_reg, int): + # Apply all transforms in reverse order of which we discovered them: We now forward propagate + # the actual value! + return functools.reduce( + lambda acc, fn: fn(acc), transforms, next_reg + ) + + if next_reg != reg: + looking_for = cls.generalize_reg(next_reg) + break + + raise BackpropagationReachedStartOfFn(looking_for) + + +class ArchitectureX86_64( # pylint: disable=invalid-name + Architecture[InstructionX86_64] +): + """The x86_64 ISA""" + + syscall_nr_register = "%eax" + syscall_argument_registers = ["%rdi", "%rsi", "%rdx", "%r10", "%r8", "%r9"] + fn_call_argument_registers = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"] + seccomp_arch = seccomp.Arch.X86_64 + + @staticmethod + def generalize_reg(reg: str) -> list[str]: + suffixes = ["ax", "bx", "cx", "dx", "si", "di", "bp", "sp"] + prefixes = ["%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"] + + for suffix in suffixes: + if reg.endswith(suffix): + return [f"%r{suffix}", f"%e{suffix}", f"%{suffix}"] + + for prefix in prefixes: + if reg.startswith(prefix): + return [prefix, f"{prefix}d", f"{prefix}w"] + + return [reg] + + +class ArchitectureAarch64(Architecture[InstructionAarch64]): + """The aarch64 ISA""" + + ALL_REGS = [f"x{i}" for i in range(0, 32)] + + syscall_nr_register = "x8" + syscall_argument_registers = ALL_REGS[:8] + fn_call_argument_registers = ALL_REGS[:8] + seccomp_arch = seccomp.Arch.AARCH64 + + @staticmethod + def generalize_reg(reg: str) -> list[str]: + mtch = re.match(r"^[xw](\d{1,2})$", reg) + + if mtch: + nr = mtch.group(1) + + return [f"x{nr}", f"w{nr}"] + + return [reg] + + +SYSCALL_WRAPPERS = ["syscall", "__syscall_cp", "__syscall_cp_c"] +SPECIFIC_SYSCALL_WRAPPERS = { + "ioctl": {"syscall": "ioctl", "nargs": 3}, + "__mmap": {"syscall": "mmap", "nargs": 6}, + "socket": {"syscall": "socket", "nargs": 3}, + "__madvise": {"syscall": "madvise", "nargs": 3}, + # special snowflake ioctl: https://github.com/kraj/musl/blob/ffb23aef7b5339b8c3234f4c6a93c488dc873919/src/termios/tcsetattr.c#L5 + "tcsetattr": { + "syscall": "ioctl", + "nargs": 3, + "arg_transform": {1: lambda x: x + 0x5402}, + }, +} + + +class Function: + """Represents a single function in the binary (e.g. as determined from DWARF debug information)""" + + def __init__(self, name: str, arch: Architecture): + self.name = name + self.instructions = [] + self.arch = arch + + def resolve_registers_before_insn(self, i: int, registers: list[str]): + """Tries to determine the values of the given registers when the i-th instruction + executes.""" + resolved_registers = {} + + for reg in registers: + try: + resolved_registers[reg] = self.arch.determine_register_value( + self.instructions[:i], reg + ) + except ( + UnsupportedInstructionError, + BackpropagationReachedStartOfFn, + ) as exc: + resolved_registers[reg] = exc + + return resolved_registers + + +class UnsupportedInstructionError(Exception): + """Exception indicating that an unsupported instruction was encountered during backpropagation, and this + unsupported instruction refers to the register being backpropagated.""" + + def __init__(self, insn: Instruction, reg: str): + super().__init__( + f"Encountered unsupported instruction during backpropagation which affects a register of interest ({reg}): {insn}" + ) + + self.instruction = insn + + +class BackpropagationReachedStartOfFn(Exception): + """Exception indicating that the beginning of a function was reached during backpropagation, without any immediate + value being loaded into the register whose value we were trying to determine""" + + def __init__(self, current_register): + super().__init__( + f"Backpropagation reached beginning of function definition while backpropagating {current_register}. Maybe it is a parameter itself?" + ) + + +def parse_objdump_output(output: str, arch: Architecture) -> list[Function]: + """Parse the stdout from obj dump into a list of the contained functions""" + lines = output.splitlines() + + # Skip the first line of the output, it's just the file format + lines = lines[2:] + + functions = [] + current_function = None + + for line in lines: + line = line.strip() + + # Skip empty lines and those just announcing the start of a new section + if not line or line.startswith("Disassembly of section"): + # all functions are separated by empty lines. This is a sanity check to ensure the regex below + # catches all functions! + current_function = None + continue + + # Start of a new function? + mtch = re.match(r"^<(.+)>:$", line) + + if mtch: + # group 0 is always the full match (e.g. in our case the entire string because we have a regex with ^ and $) + # to get the groups defined inside the regex, start at 1. + current_function = Function(mtch.group(1), arch) + functions.append(current_function) + + continue + + # otherwise, must be instruction + if not current_function: + logger.error( + "Unexpectedly found data outside of function. Skipping line %s", line + ) + continue + + current_function.instructions.append(arch.t_instruction.from_str(line)) + + return functions + + +def find_syscalls_in_binary(binary_path: Path): # pylint: disable=too-many-branches + """Statically analyzes the given binary to find all syscalls. + + Uses objdump's '-d' option, parses the output, and then at the call site of each syscall instruction + (and also of simple wrappers around it that weren't inlined during compilation), tries to determine the values + of registers holding arguments to the syscall instruction.""" + if platform.processor() == "x86_64": + arch = ArchitectureX86_64() + else: + arch = ArchitectureAarch64() + + disassembly = subprocess.check_output( + f"objdump --demangle=rust -d {binary_path} --no-show-raw-insn --no-addresses".split() + ).decode("utf-8") + + functions = parse_objdump_output(disassembly, arch) + + found_syscalls = {} + + for fn in functions: + # We don't want to find syscall instruction inside functions that we treat as synthetic syscall instructions + # themselves, because we will not be able to figure out any argument values here (since they are instead + # determined by the arguments to the function itself). Not excluding these would mean the script recognizes + # them as very broad syscall invocations (e.g. only the syscall number is known, but nothing else, meaning + # all seccomp rules that refer to this syscall are more specific and thus cannot be ruled out). + if fn.name in SYSCALL_WRAPPERS or fn.name in SPECIFIC_SYSCALL_WRAPPERS: + continue + + for i, insn in enumerate(fn.instructions): + if insn.is_syscall: + resolved_registers = fn.resolve_registers_before_insn( + i, + [arch.syscall_nr_register] + arch.syscall_argument_registers, + ) + + syscall_nr = resolved_registers.pop(arch.syscall_nr_register) + syscall_args = [ + resolved_registers[reg] for reg in arch.syscall_argument_registers + ] + elif insn.is_call: + # in objdump output, these look like 'call ', so strip the angle brackets + called = insn.args[0][1:-1] + + if called in SYSCALL_WRAPPERS: + resolved_registers = fn.resolve_registers_before_insn( + i, arch.fn_call_argument_registers + ) + + # On x86_64, we are not able to recover the 6th argument passed, since it is passed on the stack + # This is because for the syscall wrapper, the syscall number itself is passed in one of the 6 + # registers available for function arguments in the cdecl convention (instead of being passed in + # eax, which is not usually used for function arguments). + syscall_nr = resolved_registers.pop( + arch.fn_call_argument_registers[0] + ) + syscall_args = [ + resolved_registers[reg] + for reg in arch.fn_call_argument_registers[1:] + ] + elif called in SPECIFIC_SYSCALL_WRAPPERS: + resolved_registers = fn.resolve_registers_before_insn( + i, arch.fn_call_argument_registers + ) + + syscall_nr = seccomp.resolve_syscall( + arch.seccomp_arch, SPECIFIC_SYSCALL_WRAPPERS[called]["syscall"] + ) + syscall_nargs = SPECIFIC_SYSCALL_WRAPPERS[called]["nargs"] + syscall_args = [ + resolved_registers[reg] + for reg in arch.fn_call_argument_registers[:syscall_nargs] + ] + + if all(isinstance(arg, Exception) for arg in syscall_args): + logger.warning( + "Could not resolve any argument for syscall wrapper %s in function %s", + called, + fn.name, + ) + + # If the wrapper performs some transformation of an argument, apply it. + # It'd be cool to determine these automatically via back propagation or something, + # but that's a fairly complex task, and we only have a single syscall wrapper that needs this + for arg, modifier in ( + SPECIFIC_SYSCALL_WRAPPERS[called] + .get("arg_transform", {}) + .items() + ): + syscall_args[arg] = modifier(syscall_args[arg]) + else: + continue + else: + continue + + # This gets triggered in the __lockfile function on x86_64 (syscall number is loader before a branching instruction, + # but if the branch is not taken, linear execution will eventually hit a ret. So during backpropagation we + # would need to skip the section of assembly between "jmp" and "ret", but our script doesn't do anything + # sophisticated like that and thus instead tries to analyse this branch where the syscall number register + # gets clobbered, and it eventually hits a "pop" which it doesnt understand). The syscall in question is + # "futex", and we call that one a million times elsewhere anyway. + # + # See: https://github.com/kraj/musl/blob/ffb23aef7b5339b8c3234f4c6a93c488dc873919/src/stdio/__lockfile.c#L4 + if isinstance(syscall_nr, Exception): + logger.warning( + "Failed to resolve syscall number for instruction %s in function %s: %s", + insn, + fn.name, + syscall_nr, + ) + continue + + syscall_name = seccomp.resolve_syscall( + arch.seccomp_arch, syscall_nr + ).decode("utf-8") + if syscall_name not in found_syscalls: + found_syscalls[syscall_name] = [] + + found_syscalls[syscall_name].append( + [None if isinstance(arg, Exception) else arg for arg in syscall_args] + ) + + return found_syscalls + + +def load_seccomp_rules(seccomp_path: Path): + """Loads seccomp rules from the given file, and presents them as a dictionary + mapping syscalls to a list of individual filters. Each individual filter + describes some restriction of the arguments that are allowed to be passed + to the syscall.""" + filters = json.loads(seccomp_path.read_text("utf-8")) + + all_filters = ( + filters["vcpu"]["filter"] + filters["vmm"]["filter"] + filters["api"]["filter"] + ) + allowlist = defaultdict(list) + + for seccomp_filter in all_filters: + syscall_name = seccomp_filter["syscall"] + + allowlist[syscall_name].append( + {arg["index"]: arg["val"] for arg in seccomp_filter.get("args", [])} + ) + + return allowlist + + +def determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls): + """Based on the given list of syscall determined through static analysis, compute which of the + given seccomp rules are redundant. By 'redundant' we here mean that no syscall that would match + it is actually present in the given list of syscalls.""" + + # TODO: We could also determine "too broad" rules here: If all actual invocations of a syscall specific a parameter, + # but the rule does not restrict that parameter, we could recommend to strengthen the rule to specify the parameter! + + redundant_rules = [] + + for syscall, rules in seccomp_rules.items(): + for allowed_arguments in rules: + # A rule is not needed if for all actual invocation of the syscall the rule governs, + # the rule does not match. + # Here, we determine "does not match" as "the rule specifies some value for an argument of the syscall to be + # allowed, but the invocation of the syscall never passes this specified value of the argument". + # If there are no invocations of a syscall altogether, then the universal quantification will be vacuously + # true, and any rules involving that syscall are reported as non-needed. + rule_not_needed = all( + any( + actual_invocations[arg_index] is not None + and actual_invocations[arg_index] != allowed_arg + for arg_index, allowed_arg in allowed_arguments.items() + ) + for actual_invocations in found_syscalls.get(syscall, []) + ) + + if rule_not_needed: + redundant_rules.append((syscall, allowed_arguments)) + + return redundant_rules diff --git a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py new file mode 100644 index 00000000000..a61b86b5547 --- /dev/null +++ b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py @@ -0,0 +1,37 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""A test that fails if it can definitely prove a seccomp rule redundant +(although it passing does not guarantee the converse, that all rules are definitely needed).""" +import platform +from pathlib import Path + +from framework import utils +from framework.static_analysis import ( + determine_unneeded_seccomp_rules, + find_syscalls_in_binary, + load_seccomp_rules, +) + + +def test_redundant_seccomp_rules(): + """Test that fails if static analysis determines redundant seccomp rules""" + arch = platform.processor() + + nightly_toolchain = utils.check_output( + "rustup toolchain list | grep nightly" + ).stdout.strip() + target = f"{arch}-unknown-linux-musl" + + utils.check_output( + f'RUSTFLAGS="-C relocation-model=static -C link-args=-no-pie" cargo +{nightly_toolchain} -Zbuild-std=panic_abort,std build --release --target {target} -p firecracker' + ) + + found_syscalls = find_syscalls_in_binary( + Path(f"../build/cargo_target/{target}/release/firecracker") + ) + + seccomp_rules = load_seccomp_rules(Path(f"../resources/seccomp/{target}.json")) + + redundant_rules = determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls) + + assert not redundant_rules, f"Found redundant seccomp rules! {redundant_rules}" From cb9521f8c1c5763dd4314055dd44a68cdfd87fd8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 3 Dec 2024 15:28:31 +0000 Subject: [PATCH 120/464] disable static analysis seccomp test on aarch64 The nightly toolchain in our devctr is too old to successfully compile non-PIE, statically linked aarch64 executable. I have manually verified newer nightlies to work (2024-11-16 and newer), however our nightly toolchain is dictated by kani, so we need to wait for kani to release a new version that updates past this toolchain. Therefore, temporarily disable the test on aarch64. Signed-off-by: Patrick Roy --- .../build/test_seccomp_no_redundant_rules.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py index a61b86b5547..33c8764e512 100644 --- a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py +++ b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py @@ -5,6 +5,8 @@ import platform from pathlib import Path +import pytest + from framework import utils from framework.static_analysis import ( determine_unneeded_seccomp_rules, @@ -13,6 +15,10 @@ ) +@pytest.mark.skipif( + platform.machine() != "x86_64", + reason="aarch64 nightly toolchain does not support flags needed to compile analyzable binary yet", +) def test_redundant_seccomp_rules(): """Test that fails if static analysis determines redundant seccomp rules""" arch = platform.processor() From 35502a5fd2706c379caa27496ec234adc179f7a1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 22 Nov 2024 07:40:25 +0000 Subject: [PATCH 121/464] Remove some redundant seccomp entries from allow lists These have been determined by static analysis of a Firecracker binary (see also follow up commits): The removed seccomp rules here trigger syscalls that are either not present at all in the entire Firecracker binary, or are not reachable from the entry point of a specific Firecracker thread (this analysis has only been done for the vcpu thread for now, due to being fairly tricky). Some explanations for why some of these entries are no longer needed can be found below - The `uname` syscall was used back when we supported 4.14, to query the host kernel version and disable specific Firecracker features that were not supported pre-5.10 (io_uring and hugepages for memfd). With 4.14 support dropped, there are no such checks anymore. - Various KVM_SET_* ioctls do not need to be allowed on the vcpu thread, because they are all called _before_ the vcpu seccomp filters are installed (as they are only used during snapshot restore / when preparing KVM state for boot). - on aarch64, we can additionally remove KVM_{SET,GET}VCPU_EVENTS, as we never call this ioctl on arm (only on x86) Signed-off-by: Patrick Roy --- .../seccomp/aarch64-unknown-linux-musl.json | 52 ------ .../seccomp/x86_64-unknown-linux-musl.json | 154 +----------------- 2 files changed, 3 insertions(+), 203 deletions(-) diff --git a/resources/seccomp/aarch64-unknown-linux-musl.json b/resources/seccomp/aarch64-unknown-linux-musl.json index 48d94a0f050..10abb9dc9ed 100644 --- a/resources/seccomp/aarch64-unknown-linux-musl.json +++ b/resources/seccomp/aarch64-unknown-linux-musl.json @@ -42,10 +42,6 @@ { "syscall": "close" }, - { - "syscall": "uname", - "comment": "Used for getting the kernel version, for validating io_uring support" - }, { "syscall": "eventfd2", "comment": "Used for creating io_uring completion event, on drive patch" @@ -970,42 +966,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074048665, - "comment": "KVM_SET_MP_STATE" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 2151722655, - "comment": "KVM_GET_VCPU_EVENTS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1077980832, - "comment": "KVM_SET_VCPU_EVENTS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1018,18 +978,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074835116, - "comment": "KVM_SET_ONE_REG" - } - ] - }, { "syscall": "ioctl", "args": [ diff --git a/resources/seccomp/x86_64-unknown-linux-musl.json b/resources/seccomp/x86_64-unknown-linux-musl.json index 861b69c6b44..5a70f4c01d1 100644 --- a/resources/seccomp/x86_64-unknown-linux-musl.json +++ b/resources/seccomp/x86_64-unknown-linux-musl.json @@ -42,10 +42,6 @@ { "syscall": "close" }, - { - "syscall": "uname", - "comment": "Used for getting the kernel version, for validating io_uring support" - }, { "syscall": "eventfd2", "comment": "Used for creating io_uring completion event, on drive patch" @@ -111,8 +107,8 @@ "comment": "sigaltstack is used by Rust stdlib to remove alternative signal stack during thread teardown." }, { - "syscall": "getrandom", - "comment": "getrandom is used by aws-lc library which we consume in virtio-rng" + "syscall": "getrandom", + "comment": "getrandom is used by aws-lc library which we consume in virtio-rng" }, { "syscall": "accept4", @@ -214,7 +210,7 @@ }, { "syscall": "madvise", - "comment": "Used by the VirtIO balloon device and by musl for some customer workloads. It is also used by aws-lc during random number generation. They setup a memory page that mark with MADV_WIPEONFORK to be able to detect forks. They also call it with -1 to see if madvise is supported in certain platforms." + "comment": "Used by the VirtIO balloon device and by musl for some customer workloads. It is also used by aws-lc during random number generation. They setup a memory page that mark with MADV_WIPEONFORK to be able to detect forks. They also call it with -1 to see if madvise is supported in certain platforms." }, { "syscall": "mmap", @@ -978,18 +974,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074048665, - "comment": "KVM_SET_MP_STATE" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1002,18 +986,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1077980832, - "comment": "KVM_SET_VCPU_EVENTS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1038,78 +1010,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074310800, - "comment": "KVM_SET_CPUID2" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1140895375, - "comment": "KVM_SET_LAPIC" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1074310793, - "comment": "KVM_SET_MSRS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1083223682, - "comment": "KVM_SET_REGS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1094233732, - "comment": "KVM_SET_SREGS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 2154868383, - "comment": "KVM_GET_PIT2" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1158,18 +1058,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1082175138, - "comment": "KVM_SET_DEBUGREGS" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1182,18 +1070,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1342221989, - "comment": "KVM_SET_XSAVE" - } - ] - }, { "syscall": "ioctl", "args": [ @@ -1206,30 +1082,6 @@ } ] }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 1099476647, - "comment": "KVM_SET_XCRS" - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 1, - "type": "dword", - "op": "eq", - "val": 44706, - "comment": "KVM_SET_TSC_KHZ" - } - ] - }, { "syscall": "ioctl", "args": [ From 1709e4fa60a52d543623350f54c0f82f65f7c99a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:35:17 +0000 Subject: [PATCH 122/464] build(deps): Bump the firecracker group with 7 updates Bumps the firecracker group with 7 updates: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.6` | `2.0.7` | | [serde](https://github.com/serde-rs/serde) | `1.0.215` | `1.0.216` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.215` | `1.0.216` | | [semver](https://github.com/dtolnay/semver) | `1.0.23` | `1.0.24` | | [proptest](https://github.com/proptest-rs/proptest) | `1.5.0` | `1.6.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.3` | `1.2.4` | | [home](https://github.com/rust-lang/cargo) | `0.5.9` | `0.5.11` | Updates `thiserror` from 2.0.6 to 2.0.7 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.6...2.0.7) Updates `serde` from 1.0.215 to 1.0.216 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216) Updates `serde_derive` from 1.0.215 to 1.0.216 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216) Updates `semver` from 1.0.23 to 1.0.24 - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.23...1.0.24) Updates `proptest` from 1.5.0 to 1.6.0 - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/main/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/commits) Updates `cc` from 1.2.3 to 1.2.4 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.3...cc-v1.2.4) Updates `home` from 0.5.9 to 0.5.11 - [Changelog](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cargo/commits) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: home dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 61 +++++++++++++----------------- src/acpi-tables/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 4 +- src/firecracker/Cargo.toml | 8 ++-- src/jailer/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 8 ++-- 10 files changed, 45 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8be5eab9cf6..d499d3f16f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.6", + "thiserror 2.0.7", "vm-memory", "zerocopy 0.8.13", ] @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -419,7 +419,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "vmm", "vmm-sys-util", ] @@ -613,7 +613,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "timerfd", "userfaultfd", "utils", @@ -718,11 +718,11 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -798,7 +798,7 @@ dependencies = [ "libc", "log-instrument", "regex", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] @@ -863,12 +863,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - [[package]] name = "linux-loader" version = "0.13.0" @@ -975,7 +969,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1050,9 +1043,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bitflags 2.6.0", "lazy_static", @@ -1119,7 +1112,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] @@ -1197,34 +1190,34 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm-sys-util", ] [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -1277,7 +1270,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.6", + "thiserror 2.0.7", "utils", "vmm", "vmm-sys-util", @@ -1317,11 +1310,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ - "thiserror-impl 2.0.6", + "thiserror-impl 2.0.7", ] [[package]] @@ -1337,9 +1330,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", @@ -1477,7 +1470,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.6", + "thiserror 2.0.7", ] [[package]] @@ -1588,7 +1581,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.6", + "thiserror 2.0.7", "timerfd", "userfaultfd", "utils", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 87b2e7ed626..0a7f92dee5f 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.6" +thiserror = "2.0.7" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } zerocopy = { version = "0.8.13", features = ["derive"] } diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 0e665f8f521..5fd314bf48c 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -14,9 +14,9 @@ clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index ec20799e798..cbd9ffe5e2d 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -23,10 +23,10 @@ log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } @@ -38,13 +38,13 @@ libc = "0.2.168" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] bincode = "1.2.1" seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.215" } +serde = { version = "1.0.216" } serde_json = "1.0.133" [features] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index c84b09450b0..955fe1af5b2 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -15,7 +15,7 @@ bench = false libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.6" +thiserror = "2.0.7" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 8409430340e..c435d2ae249 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -13,7 +13,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.6" +thiserror = "2.0.7" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 93be7082920..4c23f0ae595 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -20,9 +20,9 @@ bincode = "1.2.1" displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.133" -thiserror = "2.0.6" +thiserror = "2.0.7" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 0e42cd11859..a199a8ab99f 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -16,8 +16,8 @@ displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -semver = "1.0.23" -thiserror = "2.0.6" +semver = "1.0.24" +thiserror = "2.0.7" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index dd5652718da..c4509ec1e57 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -12,7 +12,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.168" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.6" +thiserror = "2.0.7" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 0ab810b6573..043fc11528c 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -32,11 +32,11 @@ memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -semver = { version = "1.0.23", features = ["serde"] } -serde = { version = "1.0.215", features = ["derive", "rc"] } +semver = { version = "1.0.24", features = ["serde"] } +serde = { version = "1.0.216", features = ["derive", "rc"] } serde_json = "1.0.133" slab = "0.4.7" -thiserror = "2.0.6" +thiserror = "2.0.7" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } @@ -54,7 +54,7 @@ vm-fdt = "0.3.0" criterion = { version = "0.5.0", default-features = false } device_tree = "1.1.0" itertools = "0.13.0" -proptest = { version = "1.5.0", default-features = false, features = ["std"] } +proptest = { version = "1.6.0", default-features = false, features = ["std"] } [features] default = [] From 5c3ff0881f0cdf7ad82326408c9f10cee6b3c1c8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 16 Dec 2024 13:10:42 +0000 Subject: [PATCH 123/464] test: use fio instead of dd for performance tests In test_drive_rate_limiter, use `fio` for measuring latencies of writing a fixed number of bytes to a block device, instead of `dd` (which the test itself notes is unreliable). Should fix intermitted failures we're been seeing in this test, hopefully. Signed-off-by: Patrick Roy --- .../performance/test_drive_rate_limiter.py | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/tests/integration_tests/performance/test_drive_rate_limiter.py b/tests/integration_tests/performance/test_drive_rate_limiter.py index adeb0c25123..dbb1bfb310c 100644 --- a/tests/integration_tests/performance/test_drive_rate_limiter.py +++ b/tests/integration_tests/performance/test_drive_rate_limiter.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Tests for checking the rate limiter on /drives resources.""" - +import json import os import host_tools.drive as drive_tools @@ -12,28 +12,22 @@ def check_iops_limit(ssh_connection, block_size, count, min_time, max_time): """Verify if the rate limiter throttles block iops using dd.""" - obs = block_size + byte_count = block_size * count - dd = "dd if=/dev/zero of=/dev/vdb ibs={} obs={} count={} oflag=direct".format( - block_size, obs, count - ) - print("Running cmd {}".format(dd)) - # Check write iops (writing with oflag=direct is more reliable). - _, _, stderr = ssh_connection.check_output(dd) - # "dd" writes to stderr by design. We drop first lines - lines = stderr.split("\n") - dd_result = lines[2].strip() + fio = f"fio --name=fixed-job --direct=1 --rw=write --blocksize={block_size} --size={byte_count} --filename=/dev/vdb --zero_buffers --output-format=json" + + _, stdout, _ = ssh_connection.check_output(fio) - # Interesting output looks like this: - # 4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.0528524 s, 79.4 MB/s - tokens = dd_result.split() + data = json.loads(stdout) + runtime_ms = data["jobs"][0]["write"]["runtime"] + io_bytes = data["jobs"][0]["write"]["io_bytes"] # Check total read bytes. - assert int(tokens[0]) == byte_count + assert io_bytes == byte_count # Check duration. - assert float(tokens[7]) > min_time - assert float(tokens[7]) < max_time + assert runtime_ms > min_time * 1000 + assert runtime_ms < max_time * 1000 def test_patch_drive_limiter(uvm_plain): From 5b8e44ab2e0f4f2c67002a97470887d7afd1cb79 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 16 Dec 2024 14:15:04 +0000 Subject: [PATCH 124/464] fix(test): do not use absolute path to true when opening ssh connection In #4955 the executable to check the ssh connection liveliness was changed from `true` to `/usr/bin/true`, but that is not its path in all rootfs, causing failures in the `test-populat-containers` suite. Also, since the error is retried but the daemon is not cleaned up, subsequent retries would fail for the assertion. This change fixes both issues by using the binary name `true` and stopping the daemon on error before the next retry. Fixes: 3b2c2d4d6 ("test: use single SSH connection for lifetime of microvm") Signed-off-by: Riccardo Mancini --- tests/host_tools/network.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index ff6e58be2b9..af0b3766ee0 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -129,14 +129,21 @@ def _init_connection(self): "ControlPersist=yes", *self.options, self.user_host, - "/usr/bin/true", + "true", ] - # don't set a low timeout here, because otherwise we might get into a race condition - # where ssh already forked off the persisted connection daemon, but gets killed here - # before exiting itself. In that case, self._control_path will exist, and the retry - # will hit the assert at the start of this function. - self._exec(establish_cmd, check=True) + try: + # don't set a low timeout here, because otherwise we might get into a race condition + # where ssh already forked off the persisted connection daemon, but gets killed here + # before exiting itself. In that case, self._control_path will exist, and the retry + # will hit the assert at the start of this function. + self._exec(establish_cmd, check=True) + except Exception: + # if the control socket is present, then the daemon is running, and we should stop it + # before retrying again + if self._control_path.exists(): + self.close() + raise def _check_liveness(self) -> int: """Checks whether the ControlPersist connection is still alive""" From 89ca78177ba4ee5faeb225d2ff16641e82da2b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 12 Dec 2024 17:39:05 +0100 Subject: [PATCH 125/464] tests: prevent double publishing of metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seem that pytest_runtest_logreport is triggered for the worker where the test happens and the main process. So do not emit metrics unless we are in the main process. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index ac73b4bd8ab..865fa0b44b2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -105,6 +105,11 @@ def record_props(request, record_property): def pytest_runtest_logreport(report): """Send general test metrics to CloudWatch""" + # only publish metrics from the main process + worker_id = os.environ.get("PYTEST_XDIST_WORKER") + if worker_id is not None: + return + # The pytest's test protocol has three phases for each test item: setup, # call and teardown. At the end of each phase, pytest_runtest_logreport() # is called. @@ -135,6 +140,7 @@ def pytest_runtest_logreport(report): # and global {}, ) + METRICS.set_property("pytest_xdist_worker", worker_id) METRICS.set_property("result", report.outcome) METRICS.set_property("location", report.location) for prop_name, prop_val in report.user_properties: From 56306be408cee9b73bbb48411b3e3fbd9caff7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 13:17:22 +0100 Subject: [PATCH 126/464] tests: ignore vsock tx_flush_fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 9364472d528d380985ac0077385fc2f70e9c65bd we started to ignore tx_read_fails/tx_write_fails, but should also have included tx_flush_fails. Add it here. Fixes: 9364472d528d380985ac0077385fc2f70e9c65bd Signed-off-by: Pablo Barbáchano --- tests/host_tools/fcmetrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/host_tools/fcmetrics.py b/tests/host_tools/fcmetrics.py index e33e89089dc..47661d5b27d 100644 --- a/tests/host_tools/fcmetrics.py +++ b/tests/host_tools/fcmetrics.py @@ -472,6 +472,7 @@ def flatten_dict(node, prefix: str): # See also https://github.com/stefano-garzarella/iperf-vsock/issues/4 "fc_metrics.vsock.rx_read_fails", "fc_metrics.vsock.tx_write_fails", + "fc_metrics.vsock.tx_flush_fails", ] failure_metrics = { From c6add4fccf27cd0522a7e49a2c5dc67ab7067980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 14:52:45 +0100 Subject: [PATCH 127/464] ci: allow passing a dict/list as a step parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases we may want to pass a complex value to a step. For example: .buildkite/pipeline_pr.py \ --step-param 'retry/automatic=[{"exit_status": "*", "limit": 2}]' Signed-off-by: Pablo Barbáchano --- .buildkite/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index a8913d5d6ef..342bd671ddc 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -6,6 +6,7 @@ """ import argparse +import ast import json import os import random @@ -138,7 +139,7 @@ def __call__(self, parser, namespace, value, option_string=None): res = getattr(namespace, self.dest, {}) key_str, val = value.split("=", maxsplit=1) keys = key_str.split("/") - update = {keys[-1]: val} + update = {keys[-1]: ast.literal_eval(val)} for key in list(reversed(keys))[1:]: update = {key: update} res = overlay_dict(res, update) From 70ac1544d3bb460c47d93132f59a9e35cd5ad3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 17 Dec 2024 16:09:56 +0100 Subject: [PATCH 128/464] ci: report all microcode packages during a test run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit microcode_ctl only covers Intel firmware files. Capture AMD and any other possible ones. Signed-off-by: Pablo Barbáchano --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 7d41229b2e7..a55fda81269 100755 --- a/tools/devtool +++ b/tools/devtool @@ -742,7 +742,7 @@ cmd_test() { # If we got to here, we've got all we need to continue. say "Kernel version: $(uname -r)" say "$(sed '/^processor.*: 0$/,/^processor.*: 1$/!d; /^processor.*: 1$/d' /proc/cpuinfo)" - say "RPM microcode_ctl version: $(rpm -q microcode_ctl)" + say "RPM firmware versions: $(rpm -q microcode_ctl amd-ucode-firmware linux-firmware)" env |grep -P "^(AWS_EMF_|BUILDKITE|CODECOV_)" > env.list if [[ $performance_tweaks -eq 1 ]]; then From 32826d359f33f7d2b4d7240b32e4850d55599ebe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 16:15:17 +0000 Subject: [PATCH 129/464] build(deps): Bump the firecracker group with 10 updates Bumps the firecracker group with 10 updates: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.7` | `2.0.9` | | [syn](https://github.com/dtolnay/syn) | `2.0.90` | `2.0.91` | | [libc](https://github.com/rust-lang/libc) | `0.2.168` | `0.2.169` | | [serde_json](https://github.com/serde-rs/json) | `1.0.133` | `1.0.134` | | [env_logger](https://github.com/rust-cli/env_logger) | `0.11.5` | `0.11.6` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.11.1` | `1.12.0` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.12.15` | `0.13.0` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.23.1` | `0.24.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.4` | `1.2.5` | | [env_filter](https://github.com/rust-cli/env_logger) | `0.1.2` | `0.1.3` | Updates `thiserror` from 2.0.7 to 2.0.9 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.7...2.0.9) Updates `syn` from 2.0.90 to 2.0.91 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.90...2.0.91) Updates `libc` from 0.2.168 to 0.2.169 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.169/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.168...0.2.169) Updates `serde_json` from 1.0.133 to 1.0.134 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.133...v1.0.134) Updates `env_logger` from 0.11.5 to 0.11.6 - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.5...v0.11.6) Updates `aws-lc-rs` from 1.11.1 to 1.12.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.11.1...v1.12.0) Updates `aws-lc-fips-sys` from 0.12.15 to 0.13.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.12.15...aws-lc-fips-sys/v0.13.0) Updates `aws-lc-sys` from 0.23.1 to 0.24.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.23.1...aws-lc-sys/v0.24.0) Updates `cc` from 1.2.4 to 1.2.5 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.4...cc-v1.2.5) Updates `env_filter` from 0.1.2 to 0.1.3 - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/env_filter-v0.1.2...env_filter-v0.1.3) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: env_filter dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 65 ++++++++++++++-------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 6 +-- src/firecracker/Cargo.toml | 10 ++--- src/jailer/Cargo.toml | 4 +- src/log-instrument-macros/Cargo.toml | 2 +- src/log-instrument/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 4 +- src/seccompiler/Cargo.toml | 6 +-- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 4 +- src/vmm/Cargo.toml | 8 ++-- 13 files changed, 60 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d499d3f16f8..0d0b995381e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.7", + "thiserror 2.0.9", "vm-memory", "zerocopy 0.8.13", ] @@ -125,9 +125,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.12.15" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1e8a8e212a7851ef3d4c28cdfc017072bc684f0e0f57c7943ab60f695c3bfb" +checksum = "59057b878509d88952425fe694a2806e468612bde2d71943f3cd8034935b5032" dependencies = [ "bindgen 0.69.5", "cc", @@ -136,13 +136,14 @@ dependencies = [ "fs_extra", "libc", "paste", + "regex", ] [[package]] name = "aws-lc-rs" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" +checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -153,9 +154,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" +checksum = "8478a5c29ead3f3be14aff8a202ad965cf7da6856860041bfca271becf8ba48b" dependencies = [ "bindgen 0.69.5", "cc", @@ -260,9 +261,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -419,7 +420,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.9", "vmm", "vmm-sys-util", ] @@ -550,9 +551,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -560,9 +561,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", @@ -613,7 +614,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.9", "timerfd", "userfaultfd", "utils", @@ -798,7 +799,7 @@ dependencies = [ "libc", "log-instrument", "regex", - "thiserror 2.0.7", + "thiserror 2.0.9", "utils", "vmm-sys-util", ] @@ -849,9 +850,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -1112,7 +1113,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.7", + "thiserror 2.0.9", "utils", "vmm-sys-util", ] @@ -1190,7 +1191,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.9", "utils", "vmm-sys-util", ] @@ -1226,9 +1227,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -1270,7 +1271,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.7", + "thiserror 2.0.9", "utils", "vmm", "vmm-sys-util", @@ -1290,9 +1291,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.90" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -1310,11 +1311,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.7" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" dependencies = [ - "thiserror-impl 2.0.7", + "thiserror-impl 2.0.9", ] [[package]] @@ -1330,9 +1331,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.7" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", @@ -1470,7 +1471,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.7", + "thiserror 2.0.9", ] [[package]] @@ -1581,7 +1582,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.7", + "thiserror 2.0.9", "timerfd", "userfaultfd", "utils", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 0a7f92dee5f..7334406670a 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.7" +thiserror = "2.0.9" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } zerocopy = { version = "0.8.13", features = ["derive"] } diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index e112095226a..92dbf249fc1 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.23", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.37" -syn = { version = "2.0.90", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.91", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 5fd314bf48c..b4a8f8e3962 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -12,11 +12,11 @@ bench = false [dependencies] clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.216", features = ["derive"] } -serde_json = "1.0.133" -thiserror = "2.0.7" +serde_json = "1.0.134" +thiserror = "2.0.9" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index cbd9ffe5e2d..1f5a18d9b2e 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,15 +18,15 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } serde = { version = "1.0.216", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.133" -thiserror = "2.0.7" +serde_json = "1.0.134" +thiserror = "2.0.9" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } @@ -34,7 +34,7 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.21.0" -libc = "0.2.168" +libc = "0.2.169" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples @@ -45,7 +45,7 @@ userfaultfd = "0.8.1" bincode = "1.2.1" seccompiler = { path = "../seccompiler" } serde = { version = "1.0.216" } -serde_json = "1.0.133" +serde_json = "1.0.134" [features] tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 955fe1af5b2..4c29f53a0e1 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,10 +12,10 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.7" +thiserror = "2.0.9" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 2129df061f2..d1eb9c0b0d2 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] proc-macro2 = "1.0.92" quote = "1.0.37" -syn = { version = "2.0.90", features = ["full", "extra-traits"] } +syn = { version = "2.0.91", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index e418a7cf886..d9ea9d7dd63 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -32,7 +32,7 @@ log = "0.4.22" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] -env_logger = "0.11.5" +env_logger = "0.11.6" [lints] workspace = true diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index c435d2ae249..10d93be2712 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,9 +11,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.7" +thiserror = "2.0.9" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 4c23f0ae595..1e5cf55866a 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -18,11 +18,11 @@ bench = false [dependencies] bincode = "1.2.1" displaydoc = "0.2.5" -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.216", features = ["derive"] } -serde_json = "1.0.133" -thiserror = "2.0.7" +serde_json = "1.0.134" +thiserror = "2.0.9" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index a199a8ab99f..f57268656c4 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -14,10 +14,10 @@ clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.24" -thiserror = "2.0.7" +thiserror = "2.0.9" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index c4509ec1e57..bf8a5092968 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -10,9 +10,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.168" +libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.7" +thiserror = "2.0.9" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 043fc11528c..64e76bbc15d 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.11.1", features = ["bindgen"] } +aws-lc-rs = { version = "1.12.0", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.6.0" @@ -24,7 +24,7 @@ gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.19.1" -libc = "0.2.168" +libc = "0.2.169" linux-loader = "0.13.0" log = { version = "0.4.22", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } @@ -34,9 +34,9 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } semver = { version = "1.0.24", features = ["serde"] } serde = { version = "1.0.216", features = ["derive", "rc"] } -serde_json = "1.0.133" +serde_json = "1.0.134" slab = "0.4.7" -thiserror = "2.0.7" +thiserror = "2.0.9" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } From 5e86a2c067d51775ad1a604b7220e59569772025 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Fri, 27 Dec 2024 16:31:22 +0000 Subject: [PATCH 130/464] chore: unpin m6i/6.1 ami The volatility is not visible on the latest AMI. Signed-off-by: Nikita Kalyazin --- .buildkite/pipeline_perf.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py index 2a26f4277cc..e8169bfb2cd 100755 --- a/.buildkite/pipeline_perf.py +++ b/.buildkite/pipeline_perf.py @@ -124,8 +124,6 @@ pins = { # TODO: Unpin when performance instability on m6i/5.10 has gone. "linux_5.10-pinned": {"instance": "m6i.metal", "kv": "linux_5.10"}, - # TODO: Unpin when performance instability on m6i/6.1 has gone. - "linux_6.1-pinned": {"instance": "m6i.metal", "kv": "linux_6.1"}, } From 80b4cb4491273c76ec7c93746a36da9c7edd2388 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Tue, 24 Dec 2024 11:52:25 +0000 Subject: [PATCH 131/464] test(wrmsr): exclude MSR_IA32_SPEC_CTRL from check MSR_IA32_SPEC_CTRL is a dynamic MSR, whose value is constantly updated by the guest OS. It is not a good fit for the wrmsr test that targets static MSRs that retain their value for a long time. Signed-off-by: Nikita Kalyazin --- tests/data/msr/wrmsr_list.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/data/msr/wrmsr_list.txt b/tests/data/msr/wrmsr_list.txt index 87cc6ab1b66..a6a9e387aa4 100644 --- a/tests/data/msr/wrmsr_list.txt +++ b/tests/data/msr/wrmsr_list.txt @@ -1,5 +1,4 @@ 0x1b 0xfee00c00 -0x48 0x1 0x174 0x11 0x17a 0x1 0x1a0 0x0 From 5b706ed0450d5f52b231f1a608ddd258c7221d79 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 30 Dec 2024 14:17:34 +0000 Subject: [PATCH 132/464] test: Add pytest option to apply custom CPU template to any microVM Sometimes we would like to test a custom CPU template for debugging / testing purposes. The new pytest option `--custom-cpu-template` allows us to apply the given CPU template to any microVM in any test unless it is overwritten by a test. Since `cpu_template_any` yields not only CPU templates but also None, the given CPU template will be used in the None case. Signed-off-by: Takahiro Itazuri --- tests/conftest.py | 24 +++++++++++++++++++++++- tests/framework/microvm.py | 7 +++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 865fa0b44b2..fad3d072fe1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -23,6 +23,7 @@ """ import inspect +import json import os import re import shutil @@ -66,6 +67,14 @@ def pytest_addoption(parser): help="use firecracker/jailer binaries from this directory instead of compiling from source", ) + parser.addoption( + "--custom-cpu-template", + action="store", + help="Path to custom CPU template to be applied unless overwritten by a test", + default=None, + type=Path, + ) + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): # pylint:disable=unused-argument @@ -270,9 +279,22 @@ def microvm_factory(request, record_property, results_dir): fc_binary_path, jailer_binary_path = build_tools.get_firecracker_binaries() record_property("firecracker_bin", str(fc_binary_path)) + # If `--custom-cpu-template` option is provided, the given CPU template will + # be applied afterwards unless overwritten. + custom_cpu_template_path = request.config.getoption("--custom-cpu-template") + custom_cpu_template = ( + { + "name": custom_cpu_template_path.stem, + "template": json.loads(custom_cpu_template_path.read_text("utf-8")), + } + if custom_cpu_template_path + else None + ) # We could override the chroot base like so # jailer_kwargs={"chroot_base": "/srv/jailo"} - uvm_factory = MicroVMFactory(fc_binary_path, jailer_binary_path) + uvm_factory = MicroVMFactory( + fc_binary_path, jailer_binary_path, custom_cpu_template=custom_cpu_template + ) yield uvm_factory # if the test failed, save important files from the root of the uVM into `test_results` for troubleshooting diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 11fecf720a7..0903b689dfa 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -188,6 +188,7 @@ def __init__( monitor_memory: bool = True, jailer_kwargs: Optional[dict] = None, numa_node=None, + custom_cpu_template: Path = None, ): """Set up microVM attributes, paths, and data structures.""" # pylint: disable=too-many-statements @@ -246,6 +247,9 @@ def __init__( self.vcpus_count = None self.mem_size_bytes = None self.cpu_template_name = None + # The given custom CPU template will be set in basic_config() but could + # be overwritten via set_cpu_template(). + self.custom_cpu_template = custom_cpu_template self._connections = [] @@ -748,6 +752,9 @@ def basic_config( self.vcpus_count = vcpu_count self.mem_size_bytes = mem_size_mib * 2**20 + if self.custom_cpu_template is not None: + self.set_cpu_template(self.custom_cpu_template) + if cpu_template is not None: self.set_cpu_template(cpu_template) From e70bfabe2c547cf34f940af24e99c3b48ab5205d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 30 Dec 2024 16:25:32 +0100 Subject: [PATCH 133/464] ci: print EC2 AMI in the pytest report header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful for validation tasks and when troubleshooting. Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index fad3d072fe1..fb0fe4d5752 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -76,6 +76,11 @@ def pytest_addoption(parser): ) +def pytest_report_header(): + """Pytest hook to print relevant metadata in the logs""" + return f"EC2 AMI: {global_props.ami}" + + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): # pylint:disable=unused-argument """Plugin to get test results in fixtures From 846cdefcf57b47b5c35333e0d227fba0bc8ae46b Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 15 Nov 2024 10:47:56 +0000 Subject: [PATCH 134/464] refactor: replace PAGE_SIZE with GUEST/HOST_PAGE_SIZE Firecracker was assuming page sizes for both host and guest are 4K. But they can differ, so split into 2 values. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 3 ++- src/vmm/src/arch/mod.rs | 7 +++++-- src/vmm/src/arch/x86_64/mod.rs | 2 +- src/vmm/src/builder.rs | 4 ++-- src/vmm/src/devices/virtio/iov_deque.rs | 8 ++++---- src/vmm/src/devices/virtio/iovec.rs | 6 +++--- src/vmm/src/gdb/target.rs | 6 +++--- src/vmm/src/vstate/vm.rs | 2 +- 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 08ca1b65edb..a409f330c56 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -94,7 +94,8 @@ pub fn initrd_load_addr( guest_mem: &GuestMemoryMmap, initrd_size: usize, ) -> Result { - let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1); + let round_to_pagesize = + |size| (size + (super::GUEST_PAGE_SIZE - 1)) & !(super::GUEST_PAGE_SIZE - 1); match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) { Some(offset) => { if guest_mem.address_in_range(offset) { diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index f5a2f98cb7c..0f3bd6e46ef 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -52,8 +52,11 @@ pub struct InitrdConfig { pub size: usize, } -/// Default (smallest) memory page size for the supported architectures. -pub const PAGE_SIZE: usize = 4096; +/// Default page size for the guest OS. +pub const GUEST_PAGE_SIZE: usize = 4096; + +/// Default page size for the host OS. +pub const HOST_PAGE_SIZE: usize = 4096; impl fmt::Display for DeviceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 1066d9734c3..40f4f15607a 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -97,7 +97,7 @@ pub fn initrd_load_addr( return Err(ConfigurationError::InitrdAddress); } - let align_to_pagesize = |address| address & !(super::PAGE_SIZE - 1); + let align_to_pagesize = |address| address & !(super::GUEST_PAGE_SIZE - 1); Ok(align_to_pagesize(lowmem_size - initrd_size) as u64) } diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 8594da9f077..6131e248d91 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -1305,7 +1305,7 @@ pub(crate) mod tests { use crate::vstate::memory::GuestMemory; let image = make_test_bin(); - let mem_size: usize = image.len() * 2 + crate::arch::PAGE_SIZE; + let mem_size: usize = image.len() * 2 + crate::arch::GUEST_PAGE_SIZE; let tempfile = TempFile::new().unwrap(); let mut tempfile = tempfile.into_file(); @@ -1344,7 +1344,7 @@ pub(crate) mod tests { let tempfile = TempFile::new().unwrap(); let mut tempfile = tempfile.into_file(); tempfile.write_all(&image).unwrap(); - let gm = single_region_mem_at(crate::arch::PAGE_SIZE as u64 + 1, image.len() * 2); + let gm = single_region_mem_at(crate::arch::GUEST_PAGE_SIZE as u64 + 1, image.len() * 2); let res = load_initrd(&gm, &mut tempfile); assert!( diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs index 51bf28a49eb..994ba5cd320 100644 --- a/src/vmm/src/devices/virtio/iov_deque.rs +++ b/src/vmm/src/devices/virtio/iov_deque.rs @@ -6,7 +6,7 @@ use std::os::fd::AsRawFd; use libc::{c_int, c_void, iovec, off_t, size_t}; use memfd; -use crate::arch::PAGE_SIZE; +use crate::arch::HOST_PAGE_SIZE; #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum IovDequeError { @@ -79,8 +79,8 @@ pub enum IovDequeError { // ``` // // This value must be a multiple of 256 because this is the maximum number of `iovec` can fit into -// 1 memory page: 256 * sizeof(iovec) == 4096 == PAGE_SIZE. IovDeque only operates with `PAGE_SIZE` -// granularity. +// 1 memory page: 256 * sizeof(iovec) == 4096 == HOST_PAGE_SIZE. IovDeque only operates with +// `HOST_PAGE_SIZE` granularity. #[derive(Debug)] pub struct IovDeque { pub iov: *mut libc::iovec, @@ -93,7 +93,7 @@ unsafe impl Send for IovDeque {} impl IovDeque { const BYTES: usize = L as usize * std::mem::size_of::(); - const _ASSERT: () = assert!(Self::BYTES % PAGE_SIZE == 0); + const _ASSERT: () = assert!(Self::BYTES % HOST_PAGE_SIZE == 0); /// Create a [`memfd`] object that represents a single physical page fn create_memfd() -> Result { diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index 9262dff661b..c9893260d9e 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -815,13 +815,13 @@ mod verification { use vm_memory::VolatileSlice; use super::IoVecBuffer; + use crate::arch::GUEST_PAGE_SIZE; use crate::devices::virtio::iov_deque::IovDeque; // Redefine `IoVecBufferMut` and `IovDeque` with specific length. Otherwise // Rust will not know what to do. type IoVecBufferMutDefault = super::IoVecBufferMut; type IovDequeDefault = IovDeque; - use crate::arch::PAGE_SIZE; use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; // Maximum memory size to use for our buffers. For the time being 1KB. @@ -912,8 +912,8 @@ mod verification { // SAFETY: safe because the layout has non-zero size let mem = unsafe { std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked( - 2 * PAGE_SIZE, - PAGE_SIZE, + 2 * GUEST_PAGE_SIZE, + GUEST_PAGE_SIZE, )) }; IovDequeDefault { diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index b8230342b27..6f3f2593c15 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -33,7 +33,7 @@ use vm_memory::{Bytes, GuestAddress, GuestMemoryError}; use super::arch; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::vcpu::VcpuError as AarchVcpuError; -use crate::arch::PAGE_SIZE; +use crate::arch::GUEST_PAGE_SIZE; use crate::logger::{error, info}; use crate::utils::u64_to_usize; use crate::vstate::vcpu::VcpuSendEventError; @@ -396,7 +396,7 @@ impl MultiThreadBase for FirecrackerTarget { // Compute the amount space left in the page after the gpa let read_len = std::cmp::min( data.len(), - PAGE_SIZE - (u64_to_usize(gpa) & (PAGE_SIZE - 1)), + GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); vmm.guest_memory() @@ -430,7 +430,7 @@ impl MultiThreadBase for FirecrackerTarget { // Compute the amount space left in the page after the gpa let write_len = std::cmp::min( data.len(), - PAGE_SIZE - (u64_to_usize(gpa) & (PAGE_SIZE - 1)), + GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); vmm.guest_memory() diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 3d24dc6f9ac..d213d4d7bb6 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -593,7 +593,7 @@ pub(crate) mod tests { let res = vm.set_kvm_memory_regions(&gm, false); res.unwrap(); - // Trying to set a memory region with a size that is not a multiple of PAGE_SIZE + // Trying to set a memory region with a size that is not a multiple of GUEST_PAGE_SIZE // will result in error. let gm = single_region_mem(0x10); let res = vm.set_kvm_memory_regions(&gm, false); From 7f614b188eb96e2876fdf4bfd56956b0dbb281c4 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 15 Nov 2024 11:59:35 +0000 Subject: [PATCH 135/464] feat: query host page size Define global variable with host page size and update it at the very beginning of the main function in Firecracker. This way data types which rely on specific host page size can adapt to it. Signed-off-by: Egor Lazarchuk --- src/firecracker/src/main.rs | 5 +++++ src/vmm/src/arch/mod.rs | 18 ++++++++++++++++-- src/vmm/src/devices/virtio/iov_deque.rs | 5 +++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/firecracker/src/main.rs b/src/firecracker/src/main.rs index 8fb5392afcf..300afd0ad66 100644 --- a/src/firecracker/src/main.rs +++ b/src/firecracker/src/main.rs @@ -20,6 +20,7 @@ use seccomp::FilterError; use seccompiler::BpfThreadMap; use utils::arg_parser::{ArgParser, Argument}; use utils::validators::validate_instance_id; +use vmm::arch::host_page_size; use vmm::builder::StartMicrovmError; use vmm::logger::{ debug, error, info, LoggerConfig, ProcessTimeReporter, StoreMetric, LOGGER, METRICS, @@ -108,6 +109,10 @@ fn main_exec() -> Result<(), MainError> { // Initialize the logger. LOGGER.init().map_err(MainError::SetLogger)?; + // First call to this function updates the value to current + // host page size. + _ = host_page_size(); + // We need this so that we can reset terminal to canonical mode if panic occurs. let stdin = io::stdin(); diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 0f3bd6e46ef..a51055622e4 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use std::fmt; +use std::sync::LazyLock; +use log::warn; use serde::{Deserialize, Serialize}; /// Module for aarch64 related functionality. @@ -55,8 +57,20 @@ pub struct InitrdConfig { /// Default page size for the guest OS. pub const GUEST_PAGE_SIZE: usize = 4096; -/// Default page size for the host OS. -pub const HOST_PAGE_SIZE: usize = 4096; +/// Get the size of the host page size. +pub fn host_page_size() -> usize { + /// Default page size for the host OS. + static PAGE_SIZE: LazyLock = LazyLock::new(|| { + // # Safety: Value always valid + let r = unsafe { libc::sysconf(libc::_SC_PAGESIZE) }; + usize::try_from(r).unwrap_or_else(|_| { + warn!("Could not get host page size with sysconf, assuming default 4K host pages"); + 4096 + }) + }); + + *PAGE_SIZE +} impl fmt::Display for DeviceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs index 994ba5cd320..e3a2534994a 100644 --- a/src/vmm/src/devices/virtio/iov_deque.rs +++ b/src/vmm/src/devices/virtio/iov_deque.rs @@ -6,7 +6,7 @@ use std::os::fd::AsRawFd; use libc::{c_int, c_void, iovec, off_t, size_t}; use memfd; -use crate::arch::HOST_PAGE_SIZE; +use crate::arch::host_page_size; #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum IovDequeError { @@ -93,7 +93,6 @@ unsafe impl Send for IovDeque {} impl IovDeque { const BYTES: usize = L as usize * std::mem::size_of::(); - const _ASSERT: () = assert!(Self::BYTES % HOST_PAGE_SIZE == 0); /// Create a [`memfd`] object that represents a single physical page fn create_memfd() -> Result { @@ -153,6 +152,8 @@ impl IovDeque { /// Create a new [`IovDeque`] that can hold memory described by a single VirtIO queue. pub fn new() -> Result { + assert!(Self::BYTES % host_page_size() == 0); + let memfd = Self::create_memfd()?; let raw_memfd = memfd.as_file().as_raw_fd(); let buffer = Self::allocate_ring_buffer_memory()?; From 0123d4c0fcb5037bfda9335590e2f916ddec4f7a Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 15 Nov 2024 12:07:06 +0000 Subject: [PATCH 136/464] feat: update IovDeque to support arbitrary size and host page size Remove restriction on size and host page size. Signed-off-by: Egor Lazarchuk --- src/vmm/src/devices/virtio/iov_deque.rs | 57 ++++++++++++++++--------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs index e3a2534994a..b28d7076f43 100644 --- a/src/vmm/src/devices/virtio/iov_deque.rs +++ b/src/vmm/src/devices/virtio/iov_deque.rs @@ -77,10 +77,7 @@ pub enum IovDequeError { // pub iov_len: ::size_t, // } // ``` -// -// This value must be a multiple of 256 because this is the maximum number of `iovec` can fit into -// 1 memory page: 256 * sizeof(iovec) == 4096 == HOST_PAGE_SIZE. IovDeque only operates with -// `HOST_PAGE_SIZE` granularity. + #[derive(Debug)] pub struct IovDeque { pub iov: *mut libc::iovec, @@ -92,17 +89,15 @@ pub struct IovDeque { unsafe impl Send for IovDeque {} impl IovDeque { - const BYTES: usize = L as usize * std::mem::size_of::(); - /// Create a [`memfd`] object that represents a single physical page - fn create_memfd() -> Result { + fn create_memfd(pages_bytes: usize) -> Result { // Create a sealable memfd. let opts = memfd::MemfdOptions::default().allow_sealing(true); let mfd = opts.create("iov_deque")?; // Resize to system page size. mfd.as_file() - .set_len(Self::BYTES.try_into().unwrap()) + .set_len(pages_bytes.try_into().unwrap()) .map_err(IovDequeError::MemfdResize)?; // Add seals to prevent further resizing. @@ -135,13 +130,13 @@ impl IovDeque { /// Allocate memory for our ring buffer /// - /// This will allocate 2 * `Self::BYTES` bytes of virtual memory. - fn allocate_ring_buffer_memory() -> Result<*mut c_void, IovDequeError> { + /// This will allocate 2 * `pages_bytes` bytes of virtual memory. + fn allocate_ring_buffer_memory(pages_bytes: usize) -> Result<*mut c_void, IovDequeError> { // SAFETY: We are calling the system call with valid arguments unsafe { Self::mmap( std::ptr::null_mut(), - Self::BYTES * 2, + pages_bytes * 2, libc::PROT_NONE, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, @@ -150,20 +145,29 @@ impl IovDeque { } } + /// Calculate a number of bytes in full pages required for + /// the type to operate. + fn pages_bytes() -> usize { + let host_page_size = host_page_size(); + let bytes = L as usize * std::mem::size_of::(); + let num_host_pages = bytes.div_ceil(host_page_size); + num_host_pages * host_page_size + } + /// Create a new [`IovDeque`] that can hold memory described by a single VirtIO queue. pub fn new() -> Result { - assert!(Self::BYTES % host_page_size() == 0); + let pages_bytes = Self::pages_bytes(); - let memfd = Self::create_memfd()?; + let memfd = Self::create_memfd(pages_bytes)?; let raw_memfd = memfd.as_file().as_raw_fd(); - let buffer = Self::allocate_ring_buffer_memory()?; + let buffer = Self::allocate_ring_buffer_memory(pages_bytes)?; // Map the first page of virtual memory to the physical page described by the memfd object // SAFETY: We are calling the system call with valid arguments let _ = unsafe { Self::mmap( buffer, - Self::BYTES, + pages_bytes, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED | libc::MAP_FIXED, raw_memfd, @@ -174,17 +178,17 @@ impl IovDeque { // Map the second page of virtual memory to the physical page described by the memfd object // // SAFETY: This is safe because: - // * Both `buffer` and the result of `buffer.add(Self::BYTES)` are within bounds of the + // * Both `buffer` and the result of `buffer.add(pages_bytes)` are within bounds of the // allocation we got from `Self::allocate_ring_buffer_memory`. // * The resulting pointer is the beginning of the second page of our allocation, so it // doesn't wrap around the address space. - let next_page = unsafe { buffer.add(Self::BYTES) }; + let next_page = unsafe { buffer.add(pages_bytes) }; // SAFETY: We are calling the system call with valid arguments let _ = unsafe { Self::mmap( next_page, - Self::BYTES, + pages_bytes, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED | libc::MAP_FIXED, raw_memfd, @@ -312,9 +316,10 @@ impl IovDeque { impl Drop for IovDeque { fn drop(&mut self) { + let pages_bytes = Self::pages_bytes(); // SAFETY: We are passing an address that we got from a previous allocation of `2 * - // Self::BYTES` bytes by calling mmap - let _ = unsafe { libc::munmap(self.iov.cast(), Self::BYTES * 2) }; + // pages_bytes` by calling mmap + let _ = unsafe { libc::munmap(self.iov.cast(), 2 * pages_bytes) }; } } @@ -332,6 +337,18 @@ mod tests { assert_eq!(deque.len(), 0); } + #[test] + fn test_new_less_than_page() { + let deque = super::IovDeque::<128>::new().unwrap(); + assert_eq!(deque.len(), 0); + } + + #[test] + fn test_new_more_than_page() { + let deque = super::IovDeque::<512>::new().unwrap(); + assert_eq!(deque.len(), 0); + } + fn make_iovec(id: u16, len: u16) -> iovec { iovec { iov_base: id as *mut libc::c_void, From 11d8a01365bfa7d472e75e1dde0ac05e00fe19eb Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 21 Nov 2024 17:13:31 +0000 Subject: [PATCH 137/464] chore: add `IovDeque` fix to the CHANGELOG Add note about making `IovDeque` to work with any host page size. Signed-off-by: Egor Lazarchuk --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ef73a1e1f..e402b85ad43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ and this project adheres to - [#4921](https://github.com/firecracker-microvm/firecracker/pull/4921): Fixed swagger `CpuConfig` definition to include missing aarch64-specific fields. +- [#4916](https://github.com/firecracker-microvm/firecracker/pull/4916): Fixed + `IovDeque` implementation to work with any host page size. This fixes + virtio-net device on non 4K host kernels. ## [1.10.1] From cea24c52494b95f30e270b4cfb3a20872b02e515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 2 Jan 2025 16:51:48 +0100 Subject: [PATCH 138/464] ci: fix passing simple values to step parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In c6add4fccf27cd0522a7e49a2c5dc67ab7067980 while adding support for more complex parameters we broke passing simple strings. While it can be worked around by quoting the string with '', that makes the simple case more complex than it was before, and breaks previous pipeline definitions. Fix it so if the first character does not look like a python expression, take the value verbatim. Fixes: c6add4fccf27cd0522a7e49a2c5dc67ab7067980 Signed-off-by: Pablo Barbáchano --- .buildkite/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index 342bd671ddc..bda1ec9eccf 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -139,7 +139,8 @@ def __call__(self, parser, namespace, value, option_string=None): res = getattr(namespace, self.dest, {}) key_str, val = value.split("=", maxsplit=1) keys = key_str.split("/") - update = {keys[-1]: ast.literal_eval(val)} + # Interpret it as a literal iff it starts like one + update = {keys[-1]: ast.literal_eval(val) if val[0] in "[{'" else val} for key in list(reversed(keys))[1:]: update = {key: update} res = overlay_dict(res, update) From 7b01bdc1e44d5eb4f62aa89c2a79a05331a7ee1e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 2 Jan 2025 11:45:37 +0000 Subject: [PATCH 139/464] chore(vmm): Add pointer alignment check for Queue Raw pointers of `struct Queue` are assumed to be aligned properly; otherwise some methods (e.g. `read_volatile()`) will panic. Such an alignment is possible when restored from a broken/fuzzed snapshot. Add pointer alignment check and exit with an error early instead of panic. Signed-off-by: Takahiro Itazuri --- src/vmm/src/devices/virtio/queue.rs | 95 +++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs index 7c2c78d2407..7f595d7d9f7 100644 --- a/src/vmm/src/devices/virtio/queue.rs +++ b/src/vmm/src/devices/virtio/queue.rs @@ -34,6 +34,8 @@ pub enum QueueError { DescIndexOutOfBounds(u16), /// Failed to write value into the virtio queue used ring: {0} MemoryError(#[from] vm_memory::GuestMemoryError), + /// Pointer is not aligned properly: {0:#x} not {1}-byte aligned. + PointerNotAligned(usize, u8), } /// A virtio descriptor constraints with C representative. @@ -323,11 +325,36 @@ impl Queue { .get_slice_ptr(mem, self.used_ring_address, self.used_ring_size())? .cast(); - // Disable it for kani tests, otherwise it will hit this assertion - // and fail. - #[cfg(not(kani))] - if self.actual_size() < self.len() { - return Err(QueueError::InvalidQueueSize(self.len(), self.actual_size())); + // All the above pointers are expected to be aligned properly; otherwise some methods (e.g. + // `read_volatile()`) will panic. Such an unalignment is possible when restored from a + // broken/fuzzed snapshot. + // + // Specification of those pointers' alignments + // https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-350007 + // > ================ ========== + // > Virtqueue Part Alignment + // > ================ ========== + // > Descriptor Table 16 + // > Available Ring 2 + // > Used Ring 4 + // > ================ ========== + if !self.desc_table_ptr.cast::().is_aligned() { + return Err(QueueError::PointerNotAligned( + self.desc_table_ptr as usize, + 16, + )); + } + if !self.avail_ring_ptr.is_aligned() { + return Err(QueueError::PointerNotAligned( + self.avail_ring_ptr as usize, + 2, + )); + } + if !self.used_ring_ptr.cast::().is_aligned() { + return Err(QueueError::PointerNotAligned( + self.used_ring_ptr as usize, + 4, + )); } Ok(()) @@ -1234,7 +1261,6 @@ mod verification { #[cfg(test)] mod tests { - use vm_memory::Bytes; pub use super::*; @@ -1644,6 +1670,63 @@ mod tests { assert_eq!(q.used_ring_avail_event_get(), 1); } + #[test] + fn test_initialize_with_aligned_pointer() { + let mut q = Queue::new(0); + + let random_addr = 0x321; + // Descriptor table must be 16-byte aligned. + q.desc_table_address = GuestAddress(random_addr / 16 * 16); + // Available ring must be 2-byte aligned. + q.avail_ring_address = GuestAddress(random_addr / 2 * 2); + // Used ring must be 4-byte aligned. + q.avail_ring_address = GuestAddress(random_addr / 4 * 4); + + let mem = single_region_mem(0x1000); + q.initialize(&mem).unwrap(); + } + + #[test] + fn test_initialize_with_misaligned_pointer() { + let mut q = Queue::new(0); + let mem = single_region_mem(0x1000); + + // Descriptor table must be 16-byte aligned. + q.desc_table_address = GuestAddress(0xb); + match q.initialize(&mem) { + Ok(_) => panic!("Unexpected success"), + Err(QueueError::PointerNotAligned(addr, alignment)) => { + assert_eq!(addr % 16, 0xb); + assert_eq!(alignment, 16); + } + Err(e) => panic!("Unexpected error {e:#?}"), + } + q.desc_table_address = GuestAddress(0x0); + + // Available ring must be 2-byte aligned. + q.avail_ring_address = GuestAddress(0x1); + match q.initialize(&mem) { + Ok(_) => panic!("Unexpected success"), + Err(QueueError::PointerNotAligned(addr, alignment)) => { + assert_eq!(addr % 2, 0x1); + assert_eq!(alignment, 2); + } + Err(e) => panic!("Unexpected error {e:#?}"), + } + q.avail_ring_address = GuestAddress(0x0); + + // Used ring must be 4-byte aligned. + q.used_ring_address = GuestAddress(0x3); + match q.initialize(&mem) { + Ok(_) => panic!("unexpected success"), + Err(QueueError::PointerNotAligned(addr, alignment)) => { + assert_eq!(addr % 4, 0x3); + assert_eq!(alignment, 4); + } + Err(e) => panic!("Unexpected error {e:#?}"), + } + } + #[test] fn test_queue_error_display() { let err = QueueError::MemoryError(vm_memory::GuestMemoryError::InvalidGuestAddress( From 02ee97e2d458322c9f4b68e13426e51c916b11fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:27:15 +0000 Subject: [PATCH 140/464] build(deps): Bump the firecracker group with 7 updates Bumps the firecracker group with 7 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.13` | `0.8.14` | | [quote](https://github.com/dtolnay/quote) | `1.0.37` | `1.0.38` | | [syn](https://github.com/dtolnay/syn) | `2.0.91` | `2.0.93` | | [serde](https://github.com/serde-rs/serde) | `1.0.216` | `1.0.217` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.216` | `1.0.217` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.5` | `1.2.6` | | [glob](https://github.com/rust-lang/glob) | `0.3.1` | `0.3.2` | Updates `zerocopy` from 0.8.13 to 0.8.14 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.13...v0.8.14) Updates `quote` from 1.0.37 to 1.0.38 - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.38) Updates `syn` from 2.0.91 to 2.0.93 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.91...2.0.93) Updates `serde` from 1.0.216 to 1.0.217 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.216...v1.0.217) Updates `serde_derive` from 1.0.216 to 1.0.217 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.216...v1.0.217) Updates `cc` from 1.2.5 to 1.2.6 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.5...cc-v1.2.6) Updates `glob` from 0.3.1 to 0.3.2 - [Release notes](https://github.com/rust-lang/glob/releases) - [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/glob/compare/0.3.1...v0.3.2) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: quote dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: glob dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 38 ++++++++++++++-------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 4 +-- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 6 ++--- src/log-instrument-macros/Cargo.toml | 4 +-- src/seccompiler/Cargo.toml | 2 +- src/vmm/Cargo.toml | 4 +-- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d0b995381e..b4f5012f7ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.9", "vm-memory", - "zerocopy 0.8.13", + "zerocopy 0.8.14", ] [[package]] @@ -261,9 +261,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "jobserver", "libc", @@ -685,9 +685,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "half" @@ -1060,9 +1060,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -1207,18 +1207,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1291,9 +1291,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.91" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", @@ -1592,7 +1592,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.13", + "zerocopy 0.8.14", ] [[package]] @@ -1769,11 +1769,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67914ab451f3bfd2e69e5e9d2ef3858484e7074d63f204fd166ec391b54de21d" +checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" dependencies = [ - "zerocopy-derive 0.8.13", + "zerocopy-derive 0.8.14", ] [[package]] @@ -1789,9 +1789,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7988d73a4303ca289df03316bc490e934accf371af6bc745393cf3c2c5c4f25d" +checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 7334406670a..24924b0a691 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.9" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.13", features = ["derive"] } +zerocopy = { version = "0.8.14", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 92dbf249fc1..626f23876a8 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -13,8 +13,8 @@ bench = false clap = { version = "4.5.23", features = ["derive"] } itertools = "0.13.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } -quote = "1.0.37" -syn = { version = "2.0.91", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +quote = "1.0.38" +syn = { version = "2.0.93", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index b4a8f8e3962..a2075f6b3f3 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.216", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.134" thiserror = "2.0.9" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 1f5a18d9b2e..3f9894f0144 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -23,7 +23,7 @@ log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.216", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.134" thiserror = "2.0.9" @@ -38,13 +38,13 @@ libc = "0.2.169" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.216", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] bincode = "1.2.1" seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.216" } +serde = { version = "1.0.217" } serde_json = "1.0.134" [features] diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index d1eb9c0b0d2..e3937bbb02d 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -12,8 +12,8 @@ bench = false [dependencies] proc-macro2 = "1.0.92" -quote = "1.0.37" -syn = { version = "2.0.91", features = ["full", "extra-traits"] } +quote = "1.0.38" +syn = { version = "2.0.93", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 1e5cf55866a..67197bfb82b 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -20,7 +20,7 @@ bincode = "1.2.1" displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.216", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.134" thiserror = "2.0.9" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 64e76bbc15d..f024420e8ca 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -33,7 +33,7 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } semver = { version = "1.0.24", features = ["serde"] } -serde = { version = "1.0.216", features = ["derive", "rc"] } +serde = { version = "1.0.217", features = ["derive", "rc"] } serde_json = "1.0.134" slab = "0.4.7" thiserror = "2.0.9" @@ -45,7 +45,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.13" } +zerocopy = { version = "0.8.14" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From da47e8f1bb9773162efdddb33bc83901c9eef069 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:39:03 +0000 Subject: [PATCH 141/464] build(deps): Bump the firecracker group with 6 updates Bumps the firecracker group with 6 updates: | Package | From | To | | --- | --- | --- | | [itertools](https://github.com/rust-itertools/itertools) | `0.13.0` | `0.14.0` | | [syn](https://github.com/dtolnay/syn) | `2.0.93` | `2.0.95` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.24.0` | `0.24.1` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.6` | `1.2.7` | | [prettyplease](https://github.com/dtolnay/prettyplease) | `0.2.25` | `0.2.27` | | [winnow](https://github.com/winnow-rs/winnow) | `0.6.20` | `0.6.22` | Updates `itertools` from 0.13.0 to 0.14.0 - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.13.0...v0.14.0) Updates `syn` from 2.0.93 to 2.0.95 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.93...2.0.95) Updates `aws-lc-sys` from 0.24.0 to 0.24.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.24.0...aws-lc-sys/v0.24.1) Updates `cc` from 1.2.6 to 1.2.7 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.6...cc-v1.2.7) Updates `prettyplease` from 0.2.25 to 0.2.27 - [Release notes](https://github.com/dtolnay/prettyplease/releases) - [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.25...0.2.27) Updates `winnow` from 0.6.20 to 0.6.22 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.6.20...v0.6.22) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: prettyplease dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 35 ++++++++++++++-------------- src/clippy-tracing/Cargo.toml | 4 ++-- src/log-instrument-macros/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4f5012f7ed..8fc1d38d933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,16 +154,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8478a5c29ead3f3be14aff8a202ad965cf7da6856860041bfca271becf8ba48b" +checksum = "923ded50f602b3007e5e63e3f094c479d9c8a9b42d7f4034e4afe456aa48bfd2" dependencies = [ "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", - "libc", "paste", ] @@ -261,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", @@ -387,7 +386,7 @@ name = "clippy-tracing" version = "0.1.0" dependencies = [ "clap", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn", @@ -585,7 +584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -779,9 +778,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -1025,9 +1024,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" dependencies = [ "proc-macro2", "syn", @@ -1163,7 +1162,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1291,9 +1290,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.93" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -1567,7 +1566,7 @@ dependencies = [ "event-manager", "gdbstub", "gdbstub_arch", - "itertools 0.13.0", + "itertools 0.14.0", "kvm-bindings", "kvm-ioctls", "libc", @@ -1657,7 +1656,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1750,9 +1749,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" dependencies = [ "memchr", ] diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 626f23876a8..09c03b36b29 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -11,10 +11,10 @@ bench = false [dependencies] clap = { version = "4.5.23", features = ["derive"] } -itertools = "0.13.0" +itertools = "0.14.0" proc-macro2 = { version = "1.0.92", features = ["span-locations"] } quote = "1.0.38" -syn = { version = "2.0.93", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.95", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index e3937bbb02d..549a851a0da 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] proc-macro2 = "1.0.92" quote = "1.0.38" -syn = { version = "2.0.93", features = ["full", "extra-traits"] } +syn = { version = "2.0.95", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index f024420e8ca..c73b090a2dc 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -53,7 +53,7 @@ vm-fdt = "0.3.0" [dev-dependencies] criterion = { version = "0.5.0", default-features = false } device_tree = "1.1.0" -itertools = "0.13.0" +itertools = "0.14.0" proptest = { version = "1.6.0", default-features = false, features = ["std"] } [features] From f610cae59a5d5a174e22ccb4a6d2befa530d1c49 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 7 Jan 2025 17:16:35 +0000 Subject: [PATCH 142/464] fix: stop messing with C-states in performance tests When running performance tests, the devtool script was disabling lower C-states, leaving only C0 (e.g. "CPU actively polling for new instructions") enabled, with the goal to reduce latencies of switching between C-states, and therefore increase test stability. However, we found out that on m6i (Icelake) this was causing performance to become erratic, with most performance metrics taking on bi-modal characteristics. Since back when we originally disabled sleep states, we did not see any impact on metrics, the theory that it helps with test stability doesn't have any experimental support, so removing the C-state configuration to fix the volatility on m6i is not expected to have any drawbacks. Signed-off-by: Patrick Roy --- tools/devtool | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/tools/devtool b/tools/devtool index a55fda81269..9e71cc6191f 100755 --- a/tools/devtool +++ b/tools/devtool @@ -630,11 +630,10 @@ apply_linux_61_tweaks() { } -# Modifies the processors C- and P-state configuration (x86_64 only) for consistent performance. This means +# Modifies the processors CPU governor and P-state configuration (x86_64 only) for consistent performance. This means # - Disable turbo boost (Intel only) by writing 1 to /sys/devices/system/cpu/intel_pstate/no_turbo # - Disable turbo boost (AMD only) by writing 0 to /sys/devices/system/cpu/cpufreq/boost # - Lock the CPUs' P-state to the highest non-turbo one (Intel only) by writing 100 to /sys/devices/system/cpu/intel_pstate/{min,max}_perf_pct -# - Disable all idle C-states, meaning all CPu cores will idle by polling (busy looping) by writing 1 to /sys/devices/system/cpu/cpu*/cpuidle/state*/disable # - Set the cpu frequency governor to performance by writing "performance" to /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor apply_performance_tweaks() { # m6a instances do not support the amd_pstate driver (yet), so nothing we can do there @@ -660,15 +659,6 @@ apply_performance_tweaks() { # their maximum safe frequency. It seems to be the default for Amazon Linux, but it doesn't hurt to make this explicit. # See also https://wiki.archlinux.org/title/CPU_frequency_scaling echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor &> /dev/null - - # When a CPU core has nothing to do, it enters an idle state, also called "C-state". These are enumerated, with C0 - # being the shallowest idle state (corresponding to "currently executing instructions", aka "not actually idling"), - # and higher numbers being deeper sleep states (how many there are depends on the specific processor). The deeper - # a C-state a CPU core enters, the higher the latency to wake it up again. We can disable deeper C-states altogether - # by forcing each CPU core to constantly stay in C-0 (e.g. have them actively poll for new things to do). - # See also https://www.kernel.org/doc/html/v5.0/admin-guide/pm/cpuidle.html. - # The below also set "disable=1" on "state0", but this does not do anything (as disabling C-0 makes no sense). - echo 1 |sudo tee /sys/devices/system/cpu/cpu*/cpuidle/state*/disable &> /dev/null } unapply_performance_tweaks() { @@ -683,9 +673,6 @@ unapply_performance_tweaks() { echo 1 | sudo tee /sys/devices/system/cpu/cpufreq/boost &> /dev/null fi - # reenable deeper sleep states - echo 0 | sudo tee /sys/devices/system/cpu/cpu*/cpuidle/state*/disable &>/dev/null - # We do not reset the governor, as keeping track of each CPUs configured governor is not trivial here. On our CI # instances, the performance governor is current the default anyway (2023/11/14) } From 9ab3358e6631d7fa1905bb6eb3ce1feb4c6aace6 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 8 Jan 2025 10:47:20 +0000 Subject: [PATCH 143/464] chore: unpin cargo-deny and specify tag for libseccomp Unpin cargo-deny because rust tool-chain has been upgraded. Specify tag for libseccomp to have a fixed version. Signed-off-by: Egor Lazarchuk --- tools/devctr/Dockerfile | 10 ++++++++-- tools/devtool | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 9340c4c9c98..a9f6710a8a7 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -113,7 +113,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && rustup target add x86_64-unknown-linux-musl \ && rustup target add aarch64-unknown-linux-musl \ && rustup component add llvm-tools-preview clippy rustfmt \ - && cargo install --locked cargo-audit cargo-deny@0.16.1 grcov cargo-sort cargo-afl \ + && cargo install --locked cargo-audit cargo-deny grcov cargo-sort cargo-afl \ && cargo install --locked kani-verifier && cargo kani setup \ \ && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ @@ -149,12 +149,18 @@ RUN cd /usr/include/$ARCH-linux-musl \ && ln -s ../asm-generic asm-generic # Install static version of libseccomp -# +# We need to compile from source because +# libseccomp provided by the distribution is not +# compiled with musl-gcc and we need this +# for our musl builds. +# We specify the tag in order to have a fixed version +# of the library. RUN apt-get update \ && apt-get -y install \ libtool gperf \ && git clone https://github.com/seccomp/libseccomp /tmp/libseccomp \ && cd /tmp/libseccomp \ + && git checkout tags/v2.5.5 \ && ./autogen.sh \ && CC="musl-gcc -static" ./configure --enable-static=yes --enable-shared=false \ && make install \ diff --git a/tools/devtool b/tools/devtool index 9e71cc6191f..3c4e8834d52 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:-v76} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v77} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. From 5925eb294d54a36f6172648f1ed386649387fd96 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 8 Jan 2025 10:52:40 +0000 Subject: [PATCH 144/464] chore: allow seccomp rules integration tests to run on aarch64 Remove skip for test_redundant_seccomp_rules for aarch64. Signed-off-by: Egor Lazarchuk --- .../build/test_seccomp_no_redundant_rules.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py index 33c8764e512..a61b86b5547 100644 --- a/tests/integration_tests/build/test_seccomp_no_redundant_rules.py +++ b/tests/integration_tests/build/test_seccomp_no_redundant_rules.py @@ -5,8 +5,6 @@ import platform from pathlib import Path -import pytest - from framework import utils from framework.static_analysis import ( determine_unneeded_seccomp_rules, @@ -15,10 +13,6 @@ ) -@pytest.mark.skipif( - platform.machine() != "x86_64", - reason="aarch64 nightly toolchain does not support flags needed to compile analyzable binary yet", -) def test_redundant_seccomp_rules(): """Test that fails if static analysis determines redundant seccomp rules""" arch = platform.processor() From 8d2ab8ee71b0e0fb8e5d4bd1599a9c5dd620c157 Mon Sep 17 00:00:00 2001 From: longxiangqiao Date: Tue, 5 Nov 2024 18:50:30 +0800 Subject: [PATCH 145/464] chore: remove redundant words in comment Fix word duplicaiton in the comment. Co-Authored-By: longxiangqiao Signed-off-by: Egor Lazarchuk --- src/vmm/src/devices/virtio/vsock/packet.rs | 2 +- src/vmm/src/dumbo/tcp/connection.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmm/src/devices/virtio/vsock/packet.rs b/src/vmm/src/devices/virtio/vsock/packet.rs index f19723d25cb..fb79c76292f 100644 --- a/src/vmm/src/devices/virtio/vsock/packet.rs +++ b/src/vmm/src/devices/virtio/vsock/packet.rs @@ -518,7 +518,7 @@ mod tests { )) } - // Test case: the buffer descriptor cannot fit all the data advertised by the the + // Test case: the buffer descriptor cannot fit all the data advertised by the // packet header `len` field. { create_context!(test_ctx, handler_ctx); diff --git a/src/vmm/src/dumbo/tcp/connection.rs b/src/vmm/src/dumbo/tcp/connection.rs index 8036f428318..e17be1063af 100644 --- a/src/vmm/src/dumbo/tcp/connection.rs +++ b/src/vmm/src/dumbo/tcp/connection.rs @@ -815,7 +815,7 @@ impl Connection { /// * `mss_reserved` - How much (if anything) of the MSS value has been already used at the /// lower layers (by IP options, for example). This will be zero most of the time. /// * `payload_src` - References a buffer which contains data to send, and also specifies the - /// sequence number associated with the first byte from that that buffer. + /// sequence number associated with the first byte from that buffer. /// * `now` - An opaque timestamp representing the current moment in time. /// /// [`MAX_WINDOW_SIZE`]: ../constant.MAX_WINDOW_SIZE.html From bda67dfbfa5203ae38aee6598c5b49c32fd853ab Mon Sep 17 00:00:00 2001 From: Steven Wirges Date: Fri, 25 Oct 2024 13:33:48 +0200 Subject: [PATCH 146/464] chore: remove invalid trailing comma from the documentation Remove invalid trailing comma from a json body of a request in the documentation. Co-Authored-By: Steven Wirges Signed-off-by: Egor Lazarchuk --- docs/snapshotting/snapshot-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index c8d964ae89b..910dde94ce7 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -266,7 +266,7 @@ curl --unix-socket /tmp/firecracker.socket -i \ -d '{ "snapshot_type": "Full", "snapshot_path": "./snapshot_file", - "mem_file_path": "./mem_file", + "mem_file_path": "./mem_file" }' ``` From 03d3565a1cac7cb459f49b258e410e987c49f0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 30 Oct 2023 11:31:10 +0100 Subject: [PATCH 147/464] tests: re-use network namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-using namespaces saves a whole minute of the test run: before: 302 passed, 25 skipped in 303.29s (0:05:03) after: 301 passed, 25 skipped in 241.77s (0:04:01) Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 51 ++++++++++++++++--- tests/framework/microvm.py | 3 +- tests/host_tools/network.py | 41 +++++++++------ .../integration_tests/functional/test_api.py | 38 +++++++------- .../integration_tests/functional/test_net.py | 3 ++ 5 files changed, 92 insertions(+), 44 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fb0fe4d5752..fb1fc0a2a98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -44,6 +44,7 @@ static_cpu_templates_params, ) from host_tools.metrics import get_metrics_logger +from host_tools.network import NetNs # This codebase uses Python features available in Python 3.10 or above if sys.version_info < (3, 10): @@ -265,15 +266,46 @@ def uffd_handler_paths(): yield handlers -@pytest.fixture() -def microvm_factory(request, record_property, results_dir): - """Fixture to create microvms simply. +@pytest.fixture(scope="session") +def netns_factory(worker_id): + """A network namespace factory - In order to avoid running out of space when instantiating many microvms, - we remove the directory manually when the fixture is destroyed - (that is after every test). - One can comment the removal line, if it helps with debugging. + Network namespaces are created once per test session and re-used in subsequent tests. """ + # pylint:disable=protected-access + + class NetNsFactory: + """A Network namespace factory that reuses namespaces.""" + + def __init__(self, prefix: str): + self._all = [] + self._returned = [] + self.prefix = prefix + + def get(self, _netns_id): + """Get a free network namespace""" + if len(self._returned) > 0: + ns = self._returned.pop(0) + while ns.is_used(): + pass + return ns + ns = NetNs(self.prefix + str(len(self._all))) + # change the cleanup function so it is returned to the pool + ns._cleanup_orig = ns.cleanup + ns.cleanup = lambda: self._returned.append(ns) + self._all.append(ns) + return ns + + netns_fcty = NetNsFactory(f"netns-{worker_id}-") + yield netns_fcty.get + + for netns in netns_fcty._all: + netns._cleanup_orig() + + +@pytest.fixture() +def microvm_factory(request, record_property, results_dir, netns_factory): + """Fixture to create microvms simply.""" if binary_dir := request.config.getoption("--binary-dir"): fc_binary_path = Path(binary_dir) / "firecracker" @@ -298,7 +330,10 @@ def microvm_factory(request, record_property, results_dir): # We could override the chroot base like so # jailer_kwargs={"chroot_base": "/srv/jailo"} uvm_factory = MicroVMFactory( - fc_binary_path, jailer_binary_path, custom_cpu_template=custom_cpu_template + fc_binary_path, + jailer_binary_path, + netns_factory=netns_factory, + custom_cpu_template=custom_cpu_template, ) yield uvm_factory diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 0903b689dfa..278cb9ecd60 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -1074,6 +1074,7 @@ def __init__(self, fc_binary_path: Path, jailer_binary_path: Path, **kwargs): self.vms = [] self.fc_binary_path = Path(fc_binary_path) self.jailer_binary_path = Path(jailer_binary_path) + self.netns_factory = kwargs.pop("netns_factory", net_tools.NetNs) self.kwargs = kwargs def build(self, kernel=None, rootfs=None, **kwargs): @@ -1086,7 +1087,7 @@ def build(self, kernel=None, rootfs=None, **kwargs): jailer_binary_path=kwargs.pop( "jailer_binary_path", self.jailer_binary_path ), - netns=kwargs.pop("netns", net_tools.NetNs(microvm_id)), + netns=kwargs.pop("netns", self.netns_factory(microvm_id)), **kwargs, ) vm.netns.setup() diff --git a/tests/host_tools/network.py b/tests/host_tools/network.py index af0b3766ee0..93cdb323c50 100644 --- a/tests/host_tools/network.py +++ b/tests/host_tools/network.py @@ -251,15 +251,13 @@ def __init__(self, name, netns, ip=None): It also creates a new tap device, brings it up and moves the interface to the specified namespace. """ - # Avoid a conflict if two tests want to create the same tap device tap0 - # in the host before moving it into its own netns - temp_name = "tap" + random_str(k=8) - utils.check_output(f"ip tuntap add mode tap name {temp_name}") - utils.check_output(f"ip link set {temp_name} name {name} netns {netns}") - if ip: - utils.check_output(f"ip netns exec {netns} ifconfig {name} {ip} up") self._name = name self._netns = netns + # Create the tap device tap0 directly in the network namespace to avoid + # conflicts + self.netns.check_output(f"ip tuntap add mode tap name {name}") + if ip: + self.netns.check_output(f"ifconfig {name} {ip} up") @property def name(self): @@ -273,14 +271,10 @@ def netns(self): def set_tx_queue_len(self, tx_queue_len): """Set the length of the tap's TX queue.""" - utils.check_output( - "ip netns exec {} ip link set {} txqueuelen {}".format( - self.netns, self.name, tx_queue_len - ) - ) + self.netns.check_output(f"ip link set {self.name} txqueuelen {tx_queue_len}") def __repr__(self): - return f"" + return f"" @dataclass(frozen=True, repr=True) @@ -315,7 +309,7 @@ def with_id(i, netmask_len=30): ) -@dataclass(frozen=True, repr=True) +@dataclass(repr=True) class NetNs: """Defines a network namespace.""" @@ -334,6 +328,10 @@ def cmd_prefix(self): """Return the jailer context netns file prefix.""" return f"ip netns exec {self.id}" + def check_output(self, cmd: str): + """Run a command inside the netns.""" + return utils.check_output(f"{self.cmd_prefix()} {cmd}") + def setup(self): """Set up this network namespace.""" if not self.path.exists(): @@ -350,6 +348,19 @@ def add_tap(self, name, ip): We assume that a Tap is always configured with the same IP. """ if name not in self.taps: - tap = Tap(name, self.id, ip) + tap = Tap(name, self, ip) self.taps[name] = tap return self.taps[name] + + def is_used(self): + """Are any of the TAPs still in use + + Waits until there's no carrier signal. + Otherwise trying to reuse the TAP may return + `Resource busy (os error 16)` + """ + for tap in self.taps: + _, stdout, _ = self.check_output(f"cat /sys/class/net/{tap}/carrier") + if stdout.strip() != "0": + return True + return False diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 1e54c7b4fb1..94166374bd3 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -191,15 +191,15 @@ def test_net_api_put_update_pre_boot(uvm_plain): test_microvm = uvm_plain test_microvm.spawn() - first_if_name = "first_tap" - tap1 = net_tools.Tap(first_if_name, test_microvm.netns.id) + tap1name = test_microvm.id[:8] + "tap1" + tap1 = net_tools.Tap(tap1name, test_microvm.netns) test_microvm.api.network.put( iface_id="1", guest_mac="06:00:00:00:00:01", host_dev_name=tap1.name ) # Adding new network interfaces is allowed. - second_if_name = "second_tap" - tap2 = net_tools.Tap(second_if_name, test_microvm.netns.id) + tap2name = test_microvm.id[:8] + "tap2" + tap2 = net_tools.Tap(tap2name, test_microvm.netns) test_microvm.api.network.put( iface_id="2", guest_mac="07:00:00:00:00:01", host_dev_name=tap2.name ) @@ -209,28 +209,26 @@ def test_net_api_put_update_pre_boot(uvm_plain): expected_msg = f"The MAC address is already in use: {guest_mac}" with pytest.raises(RuntimeError, match=expected_msg): test_microvm.api.network.put( - iface_id="2", host_dev_name=second_if_name, guest_mac=guest_mac + iface_id="2", host_dev_name=tap2name, guest_mac=guest_mac ) # Updates to a network interface with an available MAC are allowed. test_microvm.api.network.put( - iface_id="2", host_dev_name=second_if_name, guest_mac="08:00:00:00:00:01" + iface_id="2", host_dev_name=tap2name, guest_mac="08:00:00:00:00:01" ) # Updates to a network interface with an unavailable name are not allowed. expected_msg = "Could not create the network device" with pytest.raises(RuntimeError, match=expected_msg): test_microvm.api.network.put( - iface_id="1", host_dev_name=second_if_name, guest_mac="06:00:00:00:00:01" + iface_id="1", host_dev_name=tap2name, guest_mac="06:00:00:00:00:01" ) # Updates to a network interface with an available name are allowed. - iface_id = "1" - tapname = test_microvm.id[:8] + "tap" + iface_id - - tap3 = net_tools.Tap(tapname, test_microvm.netns.id) + tap3name = test_microvm.id[:8] + "tap3" + tap3 = net_tools.Tap(tap3name, test_microvm.netns) test_microvm.api.network.put( - iface_id=iface_id, host_dev_name=tap3.name, guest_mac="06:00:00:00:00:01" + iface_id="3", host_dev_name=tap3.name, guest_mac="06:00:00:00:00:01" ) @@ -266,7 +264,7 @@ def test_api_mmds_config(uvm_plain): test_microvm.api.mmds_config.put(network_interfaces=["foo"]) # Attach network interface. - tap = net_tools.Tap("tap1", test_microvm.netns.id) + tap = net_tools.Tap(f"tap1-{test_microvm.id[:6]}", test_microvm.netns) test_microvm.api.network.put( iface_id="1", guest_mac="06:00:00:00:00:01", host_dev_name=tap.name ) @@ -487,7 +485,7 @@ def test_api_put_update_post_boot(uvm_plain, io_engine): iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id - tap1 = net_tools.Tap(tapname, test_microvm.netns.id) + tap1 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, host_dev_name=tap1.name, guest_mac="06:00:00:00:00:01" @@ -595,7 +593,7 @@ def test_rate_limiters_api_config(uvm_plain, io_engine): # Test network with tx bw rate-limiting. iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id - tap1 = net_tools.Tap(tapname, test_microvm.netns.id) + tap1 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, @@ -607,7 +605,7 @@ def test_rate_limiters_api_config(uvm_plain, io_engine): # Test network with rx bw rate-limiting. iface_id = "2" tapname = test_microvm.id[:8] + "tap" + iface_id - tap2 = net_tools.Tap(tapname, test_microvm.netns.id) + tap2 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, guest_mac="06:00:00:00:00:02", @@ -618,7 +616,7 @@ def test_rate_limiters_api_config(uvm_plain, io_engine): # Test network with tx and rx bw and ops rate-limiting. iface_id = "3" tapname = test_microvm.id[:8] + "tap" + iface_id - tap3 = net_tools.Tap(tapname, test_microvm.netns.id) + tap3 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, guest_mac="06:00:00:00:00:03", @@ -665,7 +663,7 @@ def test_api_patch_pre_boot(uvm_plain, io_engine): iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id - tap1 = net_tools.Tap(tapname, test_microvm.netns.id) + tap1 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, host_dev_name=tap1.name, guest_mac="06:00:00:00:00:01" ) @@ -714,7 +712,7 @@ def test_negative_api_patch_post_boot(uvm_plain, io_engine): iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id - tap1 = net_tools.Tap(tapname, test_microvm.netns.id) + tap1 = net_tools.Tap(tapname, test_microvm.netns) test_microvm.api.network.put( iface_id=iface_id, host_dev_name=tap1.name, guest_mac="06:00:00:00:00:01" ) @@ -1245,7 +1243,7 @@ def test_get_full_config(uvm_plain): # Add a net device. iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id - tap1 = net_tools.Tap(tapname, test_microvm.netns.id) + tap1 = net_tools.Tap(tapname, test_microvm.netns) guest_mac = "06:00:00:00:00:01" tx_rl = { "bandwidth": {"size": 1000000, "refill_time": 100, "one_time_burst": None}, diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index 7b784e453c5..a01157dcf76 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -83,6 +83,9 @@ def test_multi_queue_unsupported(uvm_plain): guest_mac="AA:FC:00:00:00:01", ) + # clean TAP device + utils.run_cmd(f"{microvm.netns.cmd_prefix()} ip link del name {tapname}") + @pytest.fixture def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs): From 9338d79b59ddd2e88a1172e46d555d3804410d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 20 Nov 2023 10:55:16 +0100 Subject: [PATCH 148/464] ci: increase functional test concurrency from 8 to 16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that there are no bottlenecks we can increase the concurrency of the tests. This speeds up functional test runs by 20-30% in average. | host | before (s) | after (s) | change | |----------|------------|-----------|--------| | m7g 5.10 | 195 | 161 | -18% | | m7g 6.1 | 225 | 172 | -24% | | m5n 5.10 | 466 | 274 | -40% | | m5n 6.1 | 440 | 291 | -33% | Signed-off-by: Pablo Barbáchano --- .buildkite/pipeline_cross.py | 2 +- .buildkite/pipeline_pr.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index d7cd261a3d0..1bac8c4bc3b 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -85,7 +85,7 @@ f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}.tar .", f"tar xSvf snapshots/{src_instance}_{src_kv}.tar", *pipeline.devtool_test( - pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", + pytest_opts=f"-m nonci -n8 --dist worksteal {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py", ), ], "label": f"🎬 {src_instance} {src_kv} ➡️ {dst_instance} {dst_kv}", diff --git a/.buildkite/pipeline_pr.py b/.buildkite/pipeline_pr.py index 618aa17860b..5b4693f51bd 100755 --- a/.buildkite/pipeline_pr.py +++ b/.buildkite/pipeline_pr.py @@ -76,7 +76,7 @@ pipeline.build_group( "⚙ Functional and security 🔒", pipeline.devtool_test( - pytest_opts="-n 8 --dist worksteal integration_tests/{{functional,security}}", + pytest_opts="-n 16 --dist worksteal integration_tests/{{functional,security}}", ), ) From 7e1f3d811fa9dfa79c2bbd9cefc71602bf101676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 19 Dec 2024 11:05:59 +0100 Subject: [PATCH 149/464] tests: clean up conftest.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unused import Signed-off-by: Pablo Barbáchano --- tests/conftest.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fb1fc0a2a98..8c81714f716 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,6 @@ # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -# We import some fixtures that are unused. Disable that too. -# pylint:disable=unused-import - """Imported by pytest at the start of every test session. # Fixture Goals @@ -25,12 +22,10 @@ import inspect import json import os -import re import shutil import sys import tempfile from pathlib import Path -from typing import Dict import pytest @@ -57,7 +52,7 @@ METRICS = get_metrics_logger() -PHASE_REPORT_KEY = pytest.StashKey[Dict[str, pytest.CollectReport]]() +PHASE_REPORT_KEY = pytest.StashKey[dict[str, pytest.CollectReport]]() def pytest_addoption(parser): @@ -456,19 +451,13 @@ def rootfs_rw(): @pytest.fixture def uvm_plain(microvm_factory, guest_kernel_linux_5_10, rootfs): - """Create a vanilla VM, non-parametrized - kernel: 5.10 - rootfs: Ubuntu 24.04 - """ + """Create a vanilla VM, non-parametrized""" return microvm_factory.build(guest_kernel_linux_5_10, rootfs) @pytest.fixture def uvm_plain_rw(microvm_factory, guest_kernel_linux_5_10, rootfs_rw): - """Create a vanilla VM, non-parametrized - kernel: 5.10 - rootfs: Ubuntu 24.04 - """ + """Create a vanilla VM, non-parametrized""" return microvm_factory.build(guest_kernel_linux_5_10, rootfs_rw) From 4969e47d56f5a524c8604f1447fcab6458ac3d49 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 8 Jan 2025 16:40:59 +0000 Subject: [PATCH 150/464] test: unpin m6i/5.10 AMI for perf tests With C-states renabled by f610cae59a5d ("fix: stop messing with C-states in performance tests"), the m6i volatility will be gone. Signed-off-by: Patrick Roy --- .buildkite/pipeline_perf.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py index e8169bfb2cd..a94c13b8af0 100755 --- a/.buildkite/pipeline_perf.py +++ b/.buildkite/pipeline_perf.py @@ -121,10 +121,7 @@ # } # will pin steps running on instances "m6i.metal" with kernel version tagged "linux_6.1" # to a new kernel version tagged "linux_6.1-pinned" -pins = { - # TODO: Unpin when performance instability on m6i/5.10 has gone. - "linux_5.10-pinned": {"instance": "m6i.metal", "kv": "linux_5.10"}, -} +pins = {} def apply_pins(steps): From 0e36ec47a0f94bff76677daae8e35f411d1b4bb6 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 11 Dec 2024 16:57:28 +0000 Subject: [PATCH 151/464] Use 0ms delay on latency tests Using the larger delay appears to have negative side affects on AMD Signed-off-by: Jack Thomson --- tests/integration_tests/performance/test_network_ab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/performance/test_network_ab.py b/tests/integration_tests/performance/test_network_ab.py index 60c4f17361e..3a50d864544 100644 --- a/tests/integration_tests/performance/test_network_ab.py +++ b/tests/integration_tests/performance/test_network_ab.py @@ -62,7 +62,7 @@ def test_network_latency(network_microvm, metrics): rounds = 15 request_per_round = 30 - delay = 0.2 + delay = 0.0 metrics.set_dimensions( { From a5ffb7a70ce19cb75612e0a5b402ed9438838c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 9 Jan 2025 20:10:56 +0100 Subject: [PATCH 152/464] tests: add support for amazonlinux:2023 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test AL2023 in the popular containers test. Had to rework the build rootfs script to account for some small AL2023 differences. Signed-off-by: Pablo Barbáchano --- tools/test-popular-containers/build_rootfs.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/test-popular-containers/build_rootfs.sh b/tools/test-popular-containers/build_rootfs.sh index 501197949f0..7f5eb5fbfdf 100755 --- a/tools/test-popular-containers/build_rootfs.sh +++ b/tools/test-popular-containers/build_rootfs.sh @@ -48,7 +48,6 @@ function make_rootfs { systemd-nspawn --timezone=off --pipe -i $IMG /bin/sh <>/etc/inittab ;; +amzn) + dnf update + dnf install -y openssh-server iproute passwd + # re-do this + ln -svf /etc/systemd/system/fcnet.service /etc/systemd/system/sysinit.target.wants/fcnet.service + rm -fv /etc/systemd/system/getty.target.wants/getty@tty1.service + ;; esac +passwd -d root EOF } @@ -70,3 +77,4 @@ make_rootfs ubuntu:22.04 make_rootfs ubuntu:24.04 make_rootfs ubuntu:24.10 # make_rootfs ubuntu:latest +make_rootfs amazonlinux:2023 From a7fb815f915e66316f7a0b714eb0d06edf6ebb30 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 13 Jan 2025 13:44:15 +0000 Subject: [PATCH 153/464] chore: mark Firecracker 1.8 unsupported Firecracker v1.8 had reached EOL on 2025-01-10. Signed-off-by: Egor Lazarchuk --- docs/RELEASE_POLICY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RELEASE_POLICY.md b/docs/RELEASE_POLICY.md index fe2f881d6b6..3b6b8308d45 100644 --- a/docs/RELEASE_POLICY.md +++ b/docs/RELEASE_POLICY.md @@ -92,7 +92,7 @@ v3.1 will be patched since were the last two Firecracker releases and less than | ------: | -----------: | -----------: | ------------------: | :------------------------------ | | v1.10 | 2024-11-07 | v1.10.1 | 2025-05-07 | Supported | | v1.9 | 2024-09-02 | v1.9.1 | 2025-03-02 | Supported | -| v1.8 | 2024-07-10 | v1.8.0 | 2025-01-10 | Supported | +| v1.8 | 2024-07-10 | v1.8.0 | 2025-01-10 | 2025-01-10 (end of 6mo support) | | v1.7 | 2024-03-18 | v1.7.0 | 2024-09-18 | 2024-09-18 (end of 6mo support) | | v1.6 | 2023-12-20 | v1.6.0 | 2024-06-20 | 2024-07-10 (v1.8 released) | | v1.5 | 2023-10-09 | v1.5.1 | 2024-04-09 | 2024-04-09 (end of 6mo support) | From 94826a8d7de32fc871945b7ee088f1f7d3c8a4cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:07:53 +0000 Subject: [PATCH 154/464] build(deps): Bump the firecracker group with 15 updates Bumps the firecracker group with 15 updates: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.9` | `2.0.11` | | [clap](https://github.com/clap-rs/clap) | `4.5.23` | `4.5.26` | | [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.92` | `1.0.93` | | [syn](https://github.com/dtolnay/syn) | `2.0.95` | `2.0.96` | | [uuid](https://github.com/uuid-rs/uuid) | `1.11.0` | `1.11.1` | | [serde_json](https://github.com/serde-rs/json) | `1.0.134` | `1.0.135` | | [bitflags](https://github.com/bitflags/bitflags) | `2.6.0` | `2.7.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.7` | `1.2.9` | | [clap_builder](https://github.com/clap-rs/clap) | `4.5.23` | `4.5.26` | | [clap_derive](https://github.com/clap-rs/clap) | `4.5.18` | `4.5.24` | | [linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys) | `0.4.14` | `0.4.15` | | [prettyplease](https://github.com/dtolnay/prettyplease) | `0.2.27` | `0.2.29` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.42` | `0.38.43` | | [uuid-macro-internal](https://github.com/uuid-rs/uuid) | `1.11.0` | `1.11.1` | | [winnow](https://github.com/winnow-rs/winnow) | `0.6.22` | `0.6.24` | Updates `thiserror` from 2.0.9 to 2.0.11 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.9...2.0.11) Updates `clap` from 4.5.23 to 4.5.26 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.23...clap_complete-v4.5.26) Updates `proc-macro2` from 1.0.92 to 1.0.93 - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.92...1.0.93) Updates `syn` from 2.0.95 to 2.0.96 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.95...2.0.96) Updates `uuid` from 1.11.0 to 1.11.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.11.0...1.11.1) Updates `serde_json` from 1.0.134 to 1.0.135 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.134...v1.0.135) Updates `bitflags` from 2.6.0 to 2.7.0 - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0) Updates `cc` from 1.2.7 to 1.2.9 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.7...cc-v1.2.9) Updates `clap_builder` from 4.5.23 to 4.5.26 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.23...v4.5.26) Updates `clap_derive` from 4.5.18 to 4.5.24 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.18...v4.5.24) Updates `linux-raw-sys` from 0.4.14 to 0.4.15 - [Commits](https://github.com/sunfishcode/linux-raw-sys/compare/v0.4.14...v0.4.15) Updates `prettyplease` from 0.2.27 to 0.2.29 - [Release notes](https://github.com/dtolnay/prettyplease/releases) - [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.27...0.2.29) Updates `rustix` from 0.38.42 to 0.38.43 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.42...v0.38.43) Updates `uuid-macro-internal` from 1.11.0 to 1.11.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.11.0...1.11.1) Updates `winnow` from 0.6.22 to 0.6.24 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.6.22...v0.6.24) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: bitflags dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_derive dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: linux-raw-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: prettyplease dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 104 +++++++++++++-------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 8 +-- src/cpu-template-helper/Cargo.toml | 6 +- src/firecracker/Cargo.toml | 6 +- src/jailer/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 4 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 6 +- 12 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8fc1d38d933..3e3ae133038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.9", + "thiserror 2.0.11", "vm-memory", "zerocopy 0.8.14", ] @@ -187,7 +187,7 @@ version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cexpr", "clang-sys", "lazy_static", @@ -207,7 +207,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cexpr", "clang-sys", "itertools 0.10.5", @@ -232,9 +232,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "byteorder" @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -365,9 +365,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -419,7 +419,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror 2.0.11", "vmm", "vmm-sys-util", ] @@ -613,7 +613,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.9", + "thiserror 2.0.11", "timerfd", "userfaultfd", "utils", @@ -633,7 +633,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31c683a9f13de31432e6097131d5f385898c7f0635c0f392b9d0fa165063c8ac" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg-if", "log", "managed", @@ -798,7 +798,7 @@ dependencies = [ "libc", "log-instrument", "regex", - "thiserror 2.0.9", + "thiserror 2.0.11", "utils", "vmm-sys-util", ] @@ -829,7 +829,7 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e013ae7fcd2c6a8f384104d16afe7ea02969301ea2bb2a56e44b011ebc907cab" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "kvm-bindings", "libc", "vmm-sys-util", @@ -874,9 +874,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" @@ -947,7 +947,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg-if", "libc", ] @@ -1024,9 +1024,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", "syn", @@ -1034,9 +1034,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1047,7 +1047,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "lazy_static", "num-traits", "rand", @@ -1112,7 +1112,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.9", + "thiserror 2.0.11", "utils", "vmm-sys-util", ] @@ -1154,11 +1154,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "errno", "libc", "linux-raw-sys", @@ -1190,7 +1190,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.9", + "thiserror 2.0.11", "utils", "vmm-sys-util", ] @@ -1226,9 +1226,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -1270,7 +1270,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.9", + "thiserror 2.0.11", "utils", "vmm", "vmm-sys-util", @@ -1290,9 +1290,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.95" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1310,11 +1310,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.11", ] [[package]] @@ -1330,9 +1330,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", @@ -1438,7 +1438,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d8b176d4d3e420685e964f87c25df5fdd5b26d7eb0d0e7c892d771f5b81035" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg-if", "libc", "nix", @@ -1470,14 +1470,14 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.9", + "thiserror 2.0.11", ] [[package]] name = "uuid" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4" dependencies = [ "getrandom", "rand", @@ -1486,9 +1486,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b91f57fe13a38d0ce9e28a03463d8d3c2468ed03d75375110ec71d93b449a08" +checksum = "c91084647266237a48351d05d55dee65bba9e1b597f555fcf54680f820284a1c" dependencies = [ "proc-macro2", "quote", @@ -1507,7 +1507,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bce0aad4d8776cb64f1ac591e908a561c50ba6adac4416296efee590b155623f" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "uuid", "vm-memory", @@ -1557,7 +1557,7 @@ dependencies = [ "aws-lc-rs", "base64", "bincode", - "bitflags 2.6.0", + "bitflags 2.7.0", "crc64", "criterion", "derive_more", @@ -1581,7 +1581,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.9", + "thiserror 2.0.11", "timerfd", "userfaultfd", "utils", @@ -1749,9 +1749,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.22" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 24924b0a691..17b5b5baa6f 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.9" +thiserror = "2.0.11" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } zerocopy = { version = "0.8.14", features = ["derive"] } diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 09c03b36b29..0594fc3e349 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -10,15 +10,15 @@ name = "clippy-tracing" bench = false [dependencies] -clap = { version = "4.5.23", features = ["derive"] } +clap = { version = "4.5.26", features = ["derive"] } itertools = "0.14.0" -proc-macro2 = { version = "1.0.92", features = ["span-locations"] } +proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" -syn = { version = "2.0.95", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.96", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.11.0", features = ["v4"] } +uuid = { version = "1.11.1", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index a2075f6b3f3..6ff36523398 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,13 +10,13 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.23", features = ["derive", "string"] } +clap = { version = "4.5.26", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.134" -thiserror = "2.0.9" +serde_json = "1.0.135" +thiserror = "2.0.11" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 3f9894f0144..55903bf2afe 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -25,8 +25,8 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.134" -thiserror = "2.0.9" +serde_json = "1.0.135" +thiserror = "2.0.11" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } @@ -45,7 +45,7 @@ userfaultfd = "0.8.1" bincode = "1.2.1" seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217" } -serde_json = "1.0.134" +serde_json = "1.0.135" [features] tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 4c29f53a0e1..be231386020 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -15,7 +15,7 @@ bench = false libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.9" +thiserror = "2.0.11" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 549a851a0da..471b4b66159 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -11,9 +11,9 @@ proc-macro = true bench = false [dependencies] -proc-macro2 = "1.0.92" +proc-macro2 = "1.0.93" quote = "1.0.38" -syn = { version = "2.0.95", features = ["full", "extra-traits"] } +syn = { version = "2.0.96", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 10d93be2712..f52933ddaae 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -13,7 +13,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.9" +thiserror = "2.0.11" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 67197bfb82b..a991d3652d5 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -21,8 +21,8 @@ displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.134" -thiserror = "2.0.9" +serde_json = "1.0.135" +thiserror = "2.0.11" utils = { path = "../utils" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index f57268656c4..a9bd3143b86 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,14 +10,14 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.23", features = ["derive", "string"] } +clap = { version = "4.5.26", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.24" -thiserror = "2.0.9" +thiserror = "2.0.11" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index bf8a5092968..d8b13452089 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -12,7 +12,7 @@ bench = false displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.9" +thiserror = "2.0.11" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index c73b090a2dc..8773198c002 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -15,7 +15,7 @@ arrayvec = { version = "0.7.6", optional = true } aws-lc-rs = { version = "1.12.0", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" -bitflags = "2.6.0" +bitflags = "2.7.0" crc64 = "2.0.0" derive_more = { version = "1.0.0", default-features = false, features = ["from", "display"] } displaydoc = "0.2.5" @@ -34,9 +34,9 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } seccompiler = { path = "../seccompiler" } semver = { version = "1.0.24", features = ["serde"] } serde = { version = "1.0.217", features = ["derive", "rc"] } -serde_json = "1.0.134" +serde_json = "1.0.135" slab = "0.4.7" -thiserror = "2.0.9" +thiserror = "2.0.11" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } From f7bceb6186c846bcd338299f3b91dca5d95bb21c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 16 Jan 2025 07:32:45 +0000 Subject: [PATCH 155/464] devtool: Build A and B binaries if $do_build is true If `cmd_test` is instructed to build its own binaries (e.g. being ran outside of CI), and the environment specifies that A/B-tests should be ran, then we not only need to build the currently checked out commit (the "B" revision), but also an "A" binary based on the value of the `BUILDKITE_PULL_REQUEST_BASE_BRANCH` environment variable. Signed-off-by: Patrick Roy --- tools/devtool | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 3c4e8834d52..2ab7969484b 100755 --- a/tools/devtool +++ b/tools/devtool @@ -722,7 +722,12 @@ cmd_test() { ensure_devctr ensure_build_dir ensure_ci_artifacts - [ $do_build != 0 ] && cmd_build --release + if [ $do_build != 0 ]; then + cmd_build --release + if [ -n "$BUILDKITE_PULL_REQUEST_BASE_BRANCH" ]; then + cmd_build --release --rev "$BUILDKITE_PULL_REQUEST_BASE_BRANCH" + fi + fi apply_linux_61_tweaks From 9ac6f3ab8db4d790e67b04f1bbca7c6c3c41fa4d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 16 Jan 2025 07:34:08 +0000 Subject: [PATCH 156/464] doc: Add instruction about running functional A/B-tests locally A quick blurb about which environment variables need to be set to run things like test_vulnerabilities.py locally. Signed-off-by: Patrick Roy --- tests/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/README.md b/tests/README.md index 91fb2a9aeed..1d7b7075f62 100644 --- a/tests/README.md +++ b/tests/README.md @@ -142,6 +142,21 @@ above when run on a PR will fail iff a newly added dependency has a known open RustSec advisory. If run outside a PR, it will fail if any existing dependency has an open RustSec advisory). +### Functional A/B-Tests + +Firecracker has some functional A/B-tests (for example, in +`test_vulnerabilities.py`), which generally compare the state of the pull +request target branch (e.g. `main`), with the PR head. However, when running +these locally, pytest does not know anything about potential PRs that the commit +the tests are being run on are contained in, and as such cannot do this +A/B-Test. To run functional A/B-Tests locally, you need to create a "fake" PR +environment by setting the `BUILDKITE_PULL_REQUEST` and +`BUILDKITE_PULL_REQUEST_BASE_BRANCH` environment variables: + +``` +BUILDKITE_PULL_REQUEST=true BUILDKITE_PULL_REQUEST_BASE_BRANCH=main ./tools/devtool test -- integration_tests/security/test_vulnerabilities.py +``` + ### Performance A/B-Tests Firecracker has a special framework for orchestrating long-running A/B-tests From 14cb346eeaa7a47c57364ebcafde396d01c9e776 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 22 Nov 2024 13:51:33 +0000 Subject: [PATCH 157/464] feat(seccomp): update seccompiler to use libseccomp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libseccomp provides a better quality compiler for BPF seccomp programs than our current implementation. In our testing it produces BPF code with ~65% less instructions which makes final binaries smaller which in turn makes Firecracker binary smaller because we include them into Firecracker at build time. For this transition we create a minimal set of bindings for `libseccomp` in order to simplify maintenance and avoid adding additional dependencies. The only tricky issue with this transition is the way `ioctl` and other syscalls are checked with libseccomp. It always adds a check for the high bits of the request to be 0. Unfortunately when we build with `musl`, some syscalls like `ioctl` have upper bits set to 1. Because of this, we replace `Eq` with `MaskedEq` with mask `0x00000000FFFFFFFF` when the argument is 32bits. This commit also removes dependency of firecracker and vmm crates on the seccompiler crate. Co-authored-by: Pablo Barbáchano Signed-off-by: Egor Lazarchuk --- Cargo.lock | 7 +- src/cpu-template-helper/src/utils/mod.rs | 2 +- src/firecracker/Cargo.toml | 4 +- src/firecracker/build.rs | 21 +- src/firecracker/examples/seccomp/jailer.rs | 2 +- src/firecracker/examples/seccomp/panic.rs | 2 +- src/firecracker/src/api_server/mod.rs | 6 +- src/firecracker/src/api_server_adapter.rs | 2 +- src/firecracker/src/main.rs | 2 +- src/firecracker/src/seccomp.rs | 5 +- src/seccompiler/Cargo.toml | 13 +- src/seccompiler/build.rs | 6 + src/seccompiler/src/backend.rs | 1814 ------------------ src/seccompiler/src/bin.rs | 40 + src/seccompiler/src/bindings.rs | 171 ++ src/seccompiler/src/common.rs | 25 - src/seccompiler/src/compiler.rs | 540 ------ src/seccompiler/src/lib.rs | 399 ++-- src/seccompiler/src/seccompiler_bin.rs | 578 ------ src/seccompiler/src/syscall_table/aarch64.rs | 308 --- src/seccompiler/src/syscall_table/mod.rs | 66 - src/seccompiler/src/syscall_table/x86_64.rs | 364 ---- src/seccompiler/src/types.rs | 192 ++ src/vmm/Cargo.toml | 1 - src/vmm/src/builder.rs | 8 +- src/vmm/src/lib.rs | 6 +- src/vmm/src/persist.rs | 2 +- src/vmm/src/rpc_interface.rs | 5 +- src/vmm/src/seccomp.rs | 238 +++ src/vmm/src/seccomp_filters.rs | 14 - src/vmm/src/signal_handler.rs | 144 -- src/vmm/src/test_utils/mod.rs | 2 +- src/vmm/src/vstate/vcpu/mod.rs | 6 +- src/vmm/tests/integration_tests.rs | 2 +- 34 files changed, 835 insertions(+), 4162 deletions(-) create mode 100644 src/seccompiler/build.rs delete mode 100644 src/seccompiler/src/backend.rs create mode 100644 src/seccompiler/src/bin.rs create mode 100644 src/seccompiler/src/bindings.rs delete mode 100644 src/seccompiler/src/common.rs delete mode 100644 src/seccompiler/src/compiler.rs delete mode 100644 src/seccompiler/src/seccompiler_bin.rs delete mode 100644 src/seccompiler/src/syscall_table/aarch64.rs delete mode 100644 src/seccompiler/src/syscall_table/mod.rs delete mode 100644 src/seccompiler/src/syscall_table/x86_64.rs create mode 100644 src/seccompiler/src/types.rs create mode 100644 src/vmm/src/seccomp.rs delete mode 100644 src/vmm/src/seccomp_filters.rs diff --git a/Cargo.lock b/Cargo.lock index 3e3ae133038..1e9a4972b07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -601,7 +601,6 @@ dependencies = [ name = "firecracker" version = "1.11.0-dev" dependencies = [ - "bincode", "cargo_toml", "displaydoc", "event-manager", @@ -1185,14 +1184,13 @@ name = "seccompiler" version = "1.11.0-dev" dependencies = [ "bincode", + "clap", "displaydoc", "libc", - "log-instrument", "serde", "serde_json", "thiserror 2.0.11", - "utils", - "vmm-sys-util", + "zerocopy 0.8.14", ] [[package]] @@ -1576,7 +1574,6 @@ dependencies = [ "memfd", "micro_http", "proptest", - "seccompiler", "semver", "serde", "serde_json", diff --git a/src/cpu-template-helper/src/utils/mod.rs b/src/cpu-template-helper/src/utils/mod.rs index bd570840fc5..b6d3465efd5 100644 --- a/src/cpu-template-helper/src/utils/mod.rs +++ b/src/cpu-template-helper/src/utils/mod.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, Mutex}; use vmm::builder::{build_microvm_for_boot, StartMicrovmError}; use vmm::cpu_config::templates::{CustomCpuTemplate, Numeric}; use vmm::resources::VmResources; -use vmm::seccomp_filters::get_empty_filters; +use vmm::seccomp::get_empty_filters; use vmm::vmm_config::instance_info::{InstanceInfo, VmState}; use vmm::{EventManager, Vmm, HTTP_MAX_PAYLOAD_SIZE}; use vmm_sys_util::tempfile::TempFile; diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 55903bf2afe..e6af962ea20 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -22,7 +22,6 @@ libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217", features = ["derive"] } serde_derive = "1.0.136" serde_json = "1.0.135" @@ -42,13 +41,12 @@ serde = { version = "1.0.217", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] -bincode = "1.2.1" seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217" } serde_json = "1.0.135" [features] -tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"] +tracing = ["log-instrument", "utils/tracing", "vmm/tracing"] gdb = ["vmm/gdb"] [lints] diff --git a/src/firecracker/build.rs b/src/firecracker/build.rs index b20e1cd4e1e..87710b54fc4 100644 --- a/src/firecracker/build.rs +++ b/src/firecracker/build.rs @@ -1,13 +1,8 @@ // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use std::collections::BTreeMap; -use std::fs::File; use std::path::Path; -use seccompiler::common::BpfProgram; -use seccompiler::compiler::{Compiler, JsonFile}; - const ADVANCED_BINARY_FILTER_FILE_NAME: &str = "seccomp_filter.bpf"; const JSON_DIR: &str = "../../resources/seccomp"; @@ -44,19 +39,7 @@ fn main() { // Also retrigger the build script on any seccompiler source code change. println!("cargo:rerun-if-changed={}", SECCOMPILER_SRC_DIR); - let input = std::fs::read_to_string(seccomp_json_path).expect("Correct input file"); - let filters: JsonFile = serde_json::from_str(&input).expect("Input read"); - - let arch = target_arch.as_str().try_into().expect("Target"); - let compiler = Compiler::new(arch); - - // transform the IR into a Map of BPFPrograms - let bpf_data: BTreeMap = compiler - .compile_blob(filters.0, false) - .expect("Successfull compilation"); - - // serialize the BPF programs & output them to a file let out_path = format!("{}/{}", out_dir, ADVANCED_BINARY_FILTER_FILE_NAME); - let output_file = File::create(out_path).expect("Create seccompiler output path"); - bincode::serialize_into(output_file, &bpf_data).expect("Seccompiler serialization"); + seccompiler::compile_bpf(&seccomp_json_path, &target_arch, &out_path, false) + .expect("Cannot compile seccomp filters"); } diff --git a/src/firecracker/examples/seccomp/jailer.rs b/src/firecracker/examples/seccomp/jailer.rs index f82e3f5e249..47f4a667749 100644 --- a/src/firecracker/examples/seccomp/jailer.rs +++ b/src/firecracker/examples/seccomp/jailer.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::os::unix::process::CommandExt; use std::process::{Command, Stdio}; -use seccompiler::{apply_filter, deserialize_binary}; +use vmm::seccomp::{apply_filter, deserialize_binary}; fn main() { let args: Vec = args().collect(); diff --git a/src/firecracker/examples/seccomp/panic.rs b/src/firecracker/examples/seccomp/panic.rs index 7998552a4d1..315899872f4 100644 --- a/src/firecracker/examples/seccomp/panic.rs +++ b/src/firecracker/examples/seccomp/panic.rs @@ -3,7 +3,7 @@ use std::env::args; use std::fs::File; -use seccompiler::{apply_filter, deserialize_binary}; +use vmm::seccomp::{apply_filter, deserialize_binary}; fn main() { let args: Vec = args().collect(); diff --git a/src/firecracker/src/api_server/mod.rs b/src/firecracker/src/api_server/mod.rs index 6ac2955af8f..a2edce205cd 100644 --- a/src/firecracker/src/api_server/mod.rs +++ b/src/firecracker/src/api_server/mod.rs @@ -14,13 +14,13 @@ use std::sync::mpsc; pub use micro_http::{Body, HttpServer, Request, Response, ServerError, StatusCode, Version}; use parsed_request::{ParsedRequest, RequestAction}; -use seccompiler::BpfProgramRef; use serde_json::json; use utils::time::{get_time_us, ClockType}; use vmm::logger::{ debug, error, info, update_metric_with_elapsed_time, warn, ProcessTimeReporter, METRICS, }; use vmm::rpc_interface::{ApiRequest, ApiResponse, VmmAction}; +use vmm::seccomp::BpfProgramRef; use vmm::vmm_config::snapshot::SnapshotType; use vmm_sys_util::eventfd::EventFd; @@ -78,7 +78,7 @@ impl ApiServer { // Load seccomp filters on the API thread. // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters // altogether is the desired behaviour. - if let Err(err) = seccompiler::apply_filter(seccomp_filter) { + if let Err(err) = vmm::seccomp::apply_filter(seccomp_filter) { panic!( "Failed to set the requested seccomp filters on the API thread: {}", err @@ -208,7 +208,7 @@ mod tests { use vmm::builder::StartMicrovmError; use vmm::logger::StoreMetric; use vmm::rpc_interface::{VmmActionError, VmmData}; - use vmm::seccomp_filters::get_empty_filters; + use vmm::seccomp::get_empty_filters; use vmm::vmm_config::instance_info::InstanceInfo; use vmm::vmm_config::snapshot::CreateSnapshotParams; use vmm_sys_util::tempfile::TempFile; diff --git a/src/firecracker/src/api_server_adapter.rs b/src/firecracker/src/api_server_adapter.rs index ffc4732025d..776d03a4daa 100644 --- a/src/firecracker/src/api_server_adapter.rs +++ b/src/firecracker/src/api_server_adapter.rs @@ -8,13 +8,13 @@ use std::sync::{Arc, Mutex}; use std::thread; use event_manager::{EventOps, Events, MutEventSubscriber, SubscriberOps}; -use seccompiler::BpfThreadMap; use vmm::logger::{error, warn, ProcessTimeReporter}; use vmm::resources::VmResources; use vmm::rpc_interface::{ ApiRequest, ApiResponse, BuildMicrovmFromRequestsError, PrebootApiController, RuntimeApiController, VmmAction, }; +use vmm::seccomp::BpfThreadMap; use vmm::vmm_config::instance_info::InstanceInfo; use vmm::{EventManager, FcExitCode, Vmm}; use vmm_sys_util::epoll::EventSet; diff --git a/src/firecracker/src/main.rs b/src/firecracker/src/main.rs index 300afd0ad66..27a9957d448 100644 --- a/src/firecracker/src/main.rs +++ b/src/firecracker/src/main.rs @@ -17,7 +17,6 @@ use std::{io, panic}; use api_server_adapter::ApiServerError; use event_manager::SubscriberOps; use seccomp::FilterError; -use seccompiler::BpfThreadMap; use utils::arg_parser::{ArgParser, Argument}; use utils::validators::validate_instance_id; use vmm::arch::host_page_size; @@ -27,6 +26,7 @@ use vmm::logger::{ }; use vmm::persist::SNAPSHOT_VERSION; use vmm::resources::VmResources; +use vmm::seccomp::BpfThreadMap; use vmm::signal_handler::register_signal_handlers; use vmm::snapshot::{Snapshot, SnapshotError}; use vmm::vmm_config::instance_info::{InstanceInfo, VmState}; diff --git a/src/firecracker/src/seccomp.rs b/src/firecracker/src/seccomp.rs index 5794d6498a8..2c7b3ddecd8 100644 --- a/src/firecracker/src/seccomp.rs +++ b/src/firecracker/src/seccomp.rs @@ -5,8 +5,7 @@ use std::fs::File; use std::io::{BufReader, Read}; use std::path::Path; -use seccompiler::{deserialize_binary, BpfThreadMap, DeserializationError}; -use vmm::seccomp_filters::get_empty_filters; +use vmm::seccomp::{deserialize_binary, get_empty_filters, BpfThreadMap, DeserializationError}; const THREAD_CATEGORIES: [&str; 3] = ["vmm", "api", "vcpu"]; @@ -118,7 +117,7 @@ fn filter_thread_categories(map: BpfThreadMap) -> Result Deserialize<'de> for Comment { - fn deserialize(_deserializer: D) -> std::result::Result - where - D: Deserializer<'de>, - { - String::deserialize(_deserializer)?; - - Ok(Comment {}) - } -} - -/// Seccomp filter errors. -#[derive(Debug, PartialEq, thiserror::Error, displaydoc::Display)] -pub enum FilterError { - /// The seccomp rules vector is empty. - EmptyRulesVector, - /// The seccomp filter contains too many BPF instructions. - FilterTooLarge, - /// The seccomp rule contains an invalid argument number. - InvalidArgumentNumber, - /// {0} - Arch(TargetArchError), - /// Syscall {0} has conflicting rules. - ConflictingRules(i64), -} - -/// Supported target architectures. -#[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum TargetArch { - /// x86_64 arch - x86_64, - /// aarch64 arch - aarch64, -} - -/// Errors related to target arch. -#[derive(Debug, PartialEq, thiserror::Error, displaydoc::Display)] -pub enum TargetArchError { - /// Invalid target arch string: {0} - InvalidString(String), -} - -impl TargetArch { - /// Get the arch audit value. - fn get_audit_value(self) -> u32 { - match self { - TargetArch::x86_64 => AUDIT_ARCH_X86_64, - TargetArch::aarch64 => AUDIT_ARCH_AARCH64, - } - } - - /// Get the string representation. - fn to_string(self) -> &'static str { - match self { - TargetArch::x86_64 => "x86_64", - TargetArch::aarch64 => "aarch64", - } - } -} - -impl TryInto for &str { - type Error = TargetArchError; - fn try_into(self) -> std::result::Result { - match self.to_lowercase().as_str() { - "x86_64" => Ok(TargetArch::x86_64), - "aarch64" => Ok(TargetArch::aarch64), - _ => Err(TargetArchError::InvalidString(self.to_string())), - } - } -} - -impl From for &str { - fn from(target_arch: TargetArch) -> Self { - target_arch.to_string() - } -} - -/// Comparison to perform when matching a condition. -#[derive(Clone, Debug, Deserialize, PartialEq)] -#[serde(rename_all = "snake_case")] -pub enum SeccompCmpOp { - /// Argument value is equal to the specified value. - Eq, - /// Argument value is greater than or equal to the specified value. - Ge, - /// Argument value is greater than specified value. - Gt, - /// Argument value is less than or equal to the specified value. - Le, - /// Argument value is less than specified value. - Lt, - /// Masked bits of argument value are equal to masked bits of specified value. - MaskedEq(u64), - /// Argument value is not equal to specified value. - Ne, -} - -/// Seccomp argument value length. -#[derive(Clone, Debug, Deserialize, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum SeccompCmpArgLen { - /// Argument value length is 4 bytes. - Dword, - /// Argument value length is 8 bytes. - Qword, -} - -/// Condition that syscall must match in order to satisfy a rule. -#[derive(Clone, Debug, PartialEq, Deserialize)] -#[serde(deny_unknown_fields)] -pub struct SeccompCondition { - /// Index of the argument that is to be compared. - #[serde(rename = "index")] - arg_number: u8, - /// Length of the argument value that is to be compared. - #[serde(rename = "type")] - arg_len: SeccompCmpArgLen, - /// Comparison to perform. - #[serde(rename = "op")] - operator: SeccompCmpOp, - /// The value that will be compared with the argument value. - #[serde(rename = "val")] - value: u64, - /// Optional empty value, represents a `comment` property in the JSON file. - comment: Option, -} - -/// Actions that `seccomp` can apply to process calling a syscall. -#[derive(Clone, Debug, PartialEq, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum SeccompAction { - /// Allows syscall. - Allow, - /// Returns from syscall with specified error number. - Errno(u32), - /// Kills calling thread. - KillThread, - /// Kills calling process. - KillProcess, - /// Same as allow but logs call. - Log, - /// Notifies tracing process of the caller with respective number. - Trace(u32), - /// Sends `SIGSYS` to the calling process. - Trap, -} - -/// Rule that `seccomp` attempts to match for a syscall. -/// -/// If all conditions match then rule gets matched. -/// The action of the first rule that matches will be applied to the calling process. -/// If no rule matches the default action is applied. -#[derive(Clone, Debug, PartialEq)] -pub struct SeccompRule { - /// Conditions of rule that need to match in order for the rule to get matched. - conditions: Vec, - /// Action applied to calling process if rule gets matched. - action: SeccompAction, -} - -/// Type that associates the syscall number to its SeccompRules. -pub type SeccompRuleMap = BTreeMap>; - -/// Filter containing rules assigned to syscall numbers. -#[derive(Clone, Debug, PartialEq)] -pub struct SeccompFilter { - /// Map of syscall numbers and corresponding rule chains. - rules: SeccompRuleMap, - /// Default action to apply to syscall numbers that do not exist in the hash map. - default_action: SeccompAction, - /// Target architecture of the generated BPF filter. - target_arch: TargetArch, -} - -impl SeccompCondition { - /// Validates the SeccompCondition data - pub fn validate(&self) -> Result<(), FilterError> { - // Checks that the given argument number is valid. - if self.arg_number > ARG_NUMBER_MAX { - return Err(FilterError::InvalidArgumentNumber); - } - - Ok(()) - } - - /// Splits the [`SeccompCondition`] into 32 bit chunks and offsets. - /// - /// Returns most significant half, least significant half of the `value` field of - /// [`SeccompCondition`], as well as the offsets of the most significant and least significant - /// half of the argument specified by `arg_number` relative to `struct seccomp_data` passed to - /// the BPF program by the kernel. - /// - /// [`SeccompCondition`]: struct.SeccompCondition.html - fn value_segments(&self) -> (u32, u32, u8, u8) { - // Splits the specified value into its most significant and least significant halves. - let (msb, lsb) = ((self.value >> 32) as u32, (self.value & 0xFFFFFFFF) as u32); - - // Offset to the argument specified by `arg_number`. - // Cannot overflow because the value will be at most 16 + 6 * 8 = 64. - let arg_offset = SECCOMP_DATA_ARGS_OFFSET + self.arg_number * SECCOMP_DATA_ARG_SIZE; - - // Extracts offsets of most significant and least significant halves of argument. - // Addition cannot overflow because it's at most `arg_offset` + 4 = 68. - let (msb_offset, lsb_offset) = { (arg_offset + SECCOMP_DATA_ARG_SIZE / 2, arg_offset) }; - - (msb, lsb, msb_offset, lsb_offset) - } - - /// Translates the `eq` (equal) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - /// - /// The jump is performed if the condition fails and thus the current rule does not match so - /// `seccomp` tries to match the next rule by jumping out of the current rule. - /// - /// In case the condition is part of the last rule, the jump offset is to the default action of - /// respective filter. - /// - /// The most significant and least significant halves of the argument value are compared - /// separately since the BPF operand and accumulator are 4 bytes whereas an argument value is 8. - fn into_eq_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, offset + 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, lsb, 0, offset), - ]); - bpf - } - - /// Translates the `ge` (greater than or equal) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_ge_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, msb, 3, 0), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, offset + 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, lsb, 0, offset), - ]); - bpf - } - - /// Translates the `gt` (greater than) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_gt_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, msb, 3, 0), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, offset + 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, lsb, 0, offset), - ]); - bpf - } - - /// Translates the `le` (less than or equal) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_le_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, msb, offset + 3, 0), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, lsb, offset, 0), - ]); - bpf - } - - /// Translates the `lt` (less than) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_lt_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, msb, offset + 3, 0), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, lsb, offset, 0), - ]); - bpf - } - - /// Translates the `masked_eq` (masked equal) condition into BPF statements. - /// - /// The `masked_eq` condition is `true` if the result of logical `AND` between the given value - /// and the mask is the value being compared against. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_masked_eq_bpf(self, offset: u8, mask: u64) -> Vec { - let (_, _, msb_offset, lsb_offset) = self.value_segments(); - let masked_value = self.value & mask; - let (msb, lsb) = ( - (masked_value >> 32) as u32, - (masked_value & 0xFFFFFFFF) as u32, - ); - let (mask_msb, mask_lsb) = ((mask >> 32) as u32, (mask & 0xFFFFFFFF) as u32); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_STMT(BPF_ALU + BPF_AND + BPF_K, mask_msb), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, offset + 3), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_STMT(BPF_ALU + BPF_AND + BPF_K, mask_lsb), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, lsb, 0, offset), - ]); - bpf - } - - /// Translates the `ne` (not equal) condition into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - fn into_ne_bpf(self, offset: u8) -> Vec { - let (msb, lsb, msb_offset, lsb_offset) = self.value_segments(); - - let mut bpf = match self.arg_len { - SeccompCmpArgLen::Dword => vec![], - SeccompCmpArgLen::Qword => vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(msb_offset)), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, msb, 0, 2), - ], - }; - - bpf.append(&mut vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, u32::from(lsb_offset)), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, lsb, offset, 0), - ]); - bpf - } - - /// Translates the [`SeccompCondition`] into BPF statements. - /// - /// # Arguments - /// - /// * `offset` - The given jump offset to the start of the next rule. - /// - /// [`SeccompCondition`]: struct.SeccompCondition.html - fn into_bpf(self, offset: u8) -> Vec { - let result = match self.operator { - SeccompCmpOp::Eq => self.into_eq_bpf(offset), - SeccompCmpOp::Ge => self.into_ge_bpf(offset), - SeccompCmpOp::Gt => self.into_gt_bpf(offset), - SeccompCmpOp::Le => self.into_le_bpf(offset), - SeccompCmpOp::Lt => self.into_lt_bpf(offset), - SeccompCmpOp::MaskedEq(mask) => self.into_masked_eq_bpf(offset, mask), - SeccompCmpOp::Ne => self.into_ne_bpf(offset), - }; - - // Verifies that the `CONDITION_MAX_LEN` constant was properly updated. - assert!(result.len() <= CONDITION_MAX_LEN as usize); - - result - } -} - -impl From for u32 { - /// Return codes of the BPF program for each action. - /// - /// # Arguments - /// - /// * `action` - The [`SeccompAction`] that the kernel will take. - /// - /// [`SeccompAction`]: struct.SeccompAction.html - fn from(action: SeccompAction) -> Self { - match action { - SeccompAction::Allow => SECCOMP_RET_ALLOW, - SeccompAction::Errno(x) => SECCOMP_RET_ERRNO | (x & SECCOMP_RET_MASK), - SeccompAction::KillThread => SECCOMP_RET_KILL_THREAD, - SeccompAction::KillProcess => SECCOMP_RET_KILL_PROCESS, - SeccompAction::Log => SECCOMP_RET_LOG, - SeccompAction::Trace(x) => SECCOMP_RET_TRACE | (x & SECCOMP_RET_MASK), - SeccompAction::Trap => SECCOMP_RET_TRAP, - } - } -} - -impl SeccompRule { - /// Creates a new rule. Rules with 0 conditions always match. - /// - /// # Arguments - /// - /// * `conditions` - Vector of [`SeccompCondition`] that the syscall must match. - /// * `action` - Action taken if the syscall matches the conditions. See [`SeccompAction`]. - /// - /// [`SeccompCondition`]: struct.SeccompCondition.html - /// [`SeccompAction`]: struct.SeccompAction.html - pub fn new(conditions: Vec, action: SeccompAction) -> Self { - Self { conditions, action } - } - - /// Appends a condition of the rule to an accumulator. - /// - /// The length of the rule and offset to the next rule are updated. - /// - /// # Arguments - /// - /// * `condition` - The condition added to the rule. - /// * `accumulator` - Accumulator of BPF statements that compose the BPF program. - /// * `rule_len` - Number of conditions in the rule. - /// * `offset` - Offset (in number of BPF statements) to the next rule. - fn append_condition( - condition: SeccompCondition, - accumulator: &mut Vec>, - rule_len: &mut usize, - offset: &mut u8, - ) { - // Tries to detect whether prepending the current condition will produce an unjumpable - // offset (since BPF jumps are a maximum of 255 instructions, which is u8::MAX). - if offset.checked_add(CONDITION_MAX_LEN + 1).is_none() { - // If that is the case, three additional helper jumps are prepended and the offset - // is reset to 1. - // - // - The first jump continues the evaluation of the condition chain by jumping to the - // next condition or the action of the rule if the last condition was matched. - // - The second, jumps out of the rule, to the next rule or the default action of the - // filter in case of the last rule in the rule chain of a syscall. - // - The third jumps out of the rule chain of the syscall, to the rule chain of the next - // syscall number to be checked or the default action of the filter in the case of the - // last rule chain. - let helper_jumps = vec![ - BPF_STMT(BPF_JMP + BPF_JA, 2), - BPF_STMT(BPF_JMP + BPF_JA, u32::from(*offset) + 1), - BPF_STMT(BPF_JMP + BPF_JA, u32::from(*offset) + 1), - ]; - *rule_len += helper_jumps.len(); - accumulator.push(helper_jumps); - *offset = 1; - } - - let condition = condition.into_bpf(*offset); - *rule_len += condition.len(); - // Safe to unwrap since we checked that condition length is less than `CONDITION_MAX_LEN`. - *offset += u8::try_from(condition.len()).unwrap(); - accumulator.push(condition); - } -} - -impl From for BpfProgram { - /// Translates a rule into BPF statements. - /// - /// Each rule starts with 2 jump statements: - /// * The first jump enters the rule, attempting a match. - /// * The second jump points to the end of the rule chain for one syscall, into the rule chain - /// for the next syscall or the default action if the current syscall is the last one. It - /// essentially jumps out of the current rule chain. - fn from(rule: SeccompRule) -> Self { - // Rule is built backwards, last statement is the action of the rule. - // The offset to the next rule is 1. - let mut accumulator = - Vec::with_capacity(rule.conditions.len() * CONDITION_MAX_LEN as usize); - let mut rule_len = 1; - let mut offset = 1; - accumulator.push(vec![BPF_STMT(BPF_RET + BPF_K, u32::from(rule.action))]); - - // Conditions are translated into BPF statements and prepended to the rule. - rule.conditions.into_iter().for_each(|condition| { - SeccompRule::append_condition(condition, &mut accumulator, &mut rule_len, &mut offset) - }); - - // The two initial jump statements are prepended to the rule. - let rule_jumps = vec![ - BPF_STMT(BPF_JMP + BPF_JA, 1), - BPF_STMT(BPF_JMP + BPF_JA, u32::from(offset) + 1), - ]; - rule_len += rule_jumps.len(); - accumulator.push(rule_jumps); - - // Finally, builds the translated rule by consuming the accumulator. - let mut result = Vec::with_capacity(rule_len); - accumulator - .into_iter() - .rev() - .for_each(|mut instructions| result.append(&mut instructions)); - - result - } -} - -impl SeccompFilter { - /// Creates a new filter with a set of rules and a default action. - /// - /// # Arguments - /// - /// * `rules` - Map of syscall numbers and the rules that will be applied to each of them. - /// * `default_action` - Action taken for all syscalls that do not match any rule. - /// * `target_arch` - Target architecture of the generated BPF filter. - pub fn new( - rules: SeccompRuleMap, - default_action: SeccompAction, - target_arch: &str, - ) -> Result { - let instance = Self { - rules, - default_action, - target_arch: target_arch.try_into().map_err(FilterError::Arch)?, - }; - - instance.validate()?; - - Ok(instance) - } - - /// Performs semantic checks on the SeccompFilter. - fn validate(&self) -> Result<(), FilterError> { - for (syscall_number, syscall_rules) in self.rules.iter() { - // All inserted syscalls must have at least one rule, otherwise BPF code will break. - if syscall_rules.is_empty() { - return Err(FilterError::EmptyRulesVector); - } - - // Now check for conflicting rules. - // Match on the number of empty rules for the given syscall. - // An `empty rule` is a rule that doesn't have any argument checks. - match syscall_rules - .iter() - .filter(|rule| rule.conditions.is_empty()) - .count() - { - // If the syscall has an empty rule, it may only have that rule. - 1 if syscall_rules.len() > 1 => { - return Err(FilterError::ConflictingRules(*syscall_number)); - } - // This syscall only has the one rule, so is valid. - 1 if syscall_rules.len() <= 1 => {} - // The syscall has no empty rules. - 0 => {} - // For a greater than 1 number of empty rules, error out. - _ => { - return Err(FilterError::ConflictingRules(*syscall_number)); - } - } - } - - Ok(()) - } - - /// Appends a chain of rules to an accumulator, updating the length of the filter. - /// - /// # Arguments - /// - /// * `syscall_number` - The syscall to which the rules apply. - /// * `chain` - The chain of rules for the specified syscall. - /// * `default_action` - The action to be taken in none of the rules apply. - /// * `accumulator` - The expanding BPF program. - /// * `filter_len` - The size (in number of BPF statements) of the BPF program. This is limited - /// to 4096. If the limit is exceeded, the filter is invalidated. - fn append_syscall_chain( - syscall_number: i64, - chain: Vec, - default_action: u32, - accumulator: &mut Vec>, - filter_len: &mut usize, - ) -> Result<(), FilterError> { - // The rules of the chain are translated into BPF statements. - let chain: Vec<_> = chain.into_iter().map(SeccompRule::into).collect(); - let chain_len: usize = chain.iter().map(std::vec::Vec::len).sum(); - - // The chain starts with a comparison checking the loaded syscall number against the - // syscall number of the chain. - let mut built_syscall = Vec::with_capacity(1 + chain_len + 1); - built_syscall.push(BPF_JUMP( - BPF_JMP + BPF_JEQ + BPF_K, - u32::try_from(syscall_number).unwrap(), - 0, - 1, - )); - - // The rules of the chain are appended. - chain - .into_iter() - .for_each(|mut rule| built_syscall.append(&mut rule)); - - // The default action is appended, if the syscall number comparison matched and then all - // rules fail to match, the default action is reached. - built_syscall.push(BPF_STMT(BPF_RET + BPF_K, default_action)); - - // The chain is appended to the result. - *filter_len += built_syscall.len(); - accumulator.push(built_syscall); - - // BPF programs are limited to 4096 statements. - if *filter_len >= usize::from(BPF_MAX_LEN) { - return Err(FilterError::FilterTooLarge); - } - - Ok(()) - } -} - -impl TryInto for SeccompFilter { - type Error = FilterError; - fn try_into(self) -> Result { - // Initialize the result with the precursory architecture check. - let mut result = VALIDATE_ARCHITECTURE(self.target_arch); - - // If no rules are set up, the filter will always return the default action, - // so let's short-circuit the function. - if self.rules.is_empty() { - result.extend(vec![BPF_STMT( - BPF_RET + BPF_K, - u32::from(self.default_action), - )]); - - return Ok(result); - } - - // The called syscall number is loaded. - let mut accumulator = Vec::with_capacity(1); - let mut filter_len = 1; - accumulator.push(EXAMINE_SYSCALL()); - - // Orders syscalls by priority, the highest number represents the highest priority. - let mut iter = self.rules.into_iter(); - - // For each syscall adds its rule chain to the filter. - let default_action = u32::from(self.default_action); - iter.try_for_each(|(syscall_number, chain)| { - SeccompFilter::append_syscall_chain( - syscall_number, - chain, - default_action, - &mut accumulator, - &mut filter_len, - ) - })?; - - // The default action is once again appended, it is reached if all syscall number - // comparisons fail. - filter_len += 1; - accumulator.push(vec![BPF_STMT(BPF_RET + BPF_K, default_action)]); - - // Finally, builds the translated filter by consuming the accumulator. - result.reserve(filter_len); - accumulator - .into_iter() - .for_each(|mut instructions| result.append(&mut instructions)); - - if result.len() >= usize::from(BPF_MAX_LEN) { - return Err(FilterError::FilterTooLarge); - } - - Ok(result) - } -} - -/// Builds a `jump` BPF instruction. -/// -/// # Arguments -/// -/// * `code` - The operation code. -/// * `jt` - The jump offset in case the operation returns `true`. -/// * `jf` - The jump offset in case the operation returns `false`. -/// * `k` - The operand. -#[allow(non_snake_case)] -#[inline(always)] -fn BPF_JUMP(code: u16, k: u32, jt: u8, jf: u8) -> sock_filter { - sock_filter { code, jt, jf, k } -} - -/// Builds a "statement" BPF instruction. -/// -/// # Arguments -/// -/// * `code` - The operation code. -/// * `k` - The operand. -#[allow(non_snake_case)] -#[inline(always)] -fn BPF_STMT(code: u16, k: u32) -> sock_filter { - sock_filter { - code, - jt: 0, - jf: 0, - k, - } -} - -/// Builds a sequence of BPF instructions that validate the underlying architecture. -#[allow(non_snake_case)] -#[inline(always)] -fn VALIDATE_ARCHITECTURE(target_arch: TargetArch) -> Vec { - let audit_arch_value = target_arch.get_audit_value(); - vec![ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 4), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, audit_arch_value, 1, 0), - BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS), - ] -} - -/// Builds a sequence of BPF instructions that are followed by syscall examination. -#[allow(non_snake_case)] -#[inline(always)] -fn EXAMINE_SYSCALL() -> Vec { - vec![BPF_STMT( - BPF_LD + BPF_W + BPF_ABS, - u32::from(SECCOMP_DATA_NR_OFFSET), - )] -} - -#[cfg(test)] -mod tests { - #![allow(clippy::undocumented_unsafe_blocks)] - use std::env::consts::ARCH; - use std::thread; - - use super::SeccompCmpOp::*; - use super::{SeccompCmpArgLen as ArgLen, SeccompCondition as Cond, *}; - - // BPF structure definition for filter array. - // See /usr/include/linux/filter.h . - #[repr(C)] - struct sock_fprog { - pub len: ::std::os::raw::c_ushort, - pub filter: *const sock_filter, - } - - // Builds the (syscall, rules) tuple for allowing a syscall with certain arguments. - fn allow_syscall_if(syscall_number: i64, rules: Vec) -> (i64, Vec) { - (syscall_number, rules) - } - - impl SeccompCondition { - /// Creates a new `SeccompCondition`. - pub fn new( - arg_number: u8, - arg_len: SeccompCmpArgLen, - operator: SeccompCmpOp, - value: u64, - ) -> Result { - let instance = Self { - arg_number, - arg_len, - operator, - value, - comment: None, - }; - - instance.validate().map(|_| Ok(instance))? - } - } - - // The type of the `req` parameter is different for the `musl` library. This will enable - // successful build for other non-musl libraries. - #[cfg(target_env = "musl")] - type IoctlRequest = i32; - #[cfg(not(target_env = "musl"))] - type IoctlRequest = u64; - - // We use KVM_GET_PIT2 as the second parameter for ioctl syscalls in some unit tests - // because it's a corner case. More details - // [here](https://github.com/firecracker-microvm/firecracker/issues/1206) - const KVM_GET_PIT2: u64 = 0x8070_ae9f; - const KVM_GET_PIT2_MSB: u64 = 0x0000_ae9f; - const KVM_GET_PIT2_LSB: u64 = 0x8070_0000; - - const EXTRA_SYSCALLS: [i64; 6] = [ - libc::SYS_rt_sigprocmask, - libc::SYS_sigaltstack, - libc::SYS_munmap, - libc::SYS_exit, - libc::SYS_rt_sigreturn, - libc::SYS_futex, - ]; - - fn install_filter(bpf_filter: BpfProgram) { - unsafe { - { - let rc = libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); - assert_eq!(rc, 0); - } - let bpf_prog = sock_fprog { - len: u16::try_from(bpf_filter.len()).unwrap(), - filter: bpf_filter.as_ptr(), - }; - let bpf_prog_ptr = &bpf_prog as *const sock_fprog; - { - let rc = libc::prctl( - libc::PR_SET_SECCOMP, - libc::SECCOMP_MODE_FILTER, - bpf_prog_ptr, - ); - assert_eq!(rc, 0); - } - } - } - - fn validate_seccomp_filter( - rules: Vec<(i64, Vec)>, - validation_fn: fn(), - should_fail: bool, - ) { - let failure_code: i32 = 1000; - - let mut rule_map: SeccompRuleMap = rules.into_iter().collect(); - - for syscall in EXTRA_SYSCALLS.iter() { - rule_map - .entry(*syscall) - .or_default() - .append(&mut vec![SeccompRule::new(vec![], SeccompAction::Allow)]); - } - - // Build seccomp filter. - let filter = SeccompFilter::new( - rule_map, - SeccompAction::Errno(u32::try_from(failure_code).unwrap()), - ARCH, - ) - .unwrap(); - - // We need to run the validation inside another thread in order to avoid setting - // the seccomp filter for the entire unit tests process. - let errno = thread::spawn(move || { - // Install the filter. - install_filter(filter.try_into().unwrap()); - - // Call the validation fn. - validation_fn(); - - // Return errno. - std::io::Error::last_os_error().raw_os_error().unwrap() - }) - .join() - .unwrap(); - - // In case of a seccomp denial `errno` should be `failure_code` - if should_fail { - assert_eq!(errno, failure_code); - } else { - assert_ne!(errno, failure_code); - } - } - - #[test] - fn test_eq_operator() { - // check use cases for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Eq, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0); - }, - true, - ); - - // check use cases for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Eq, u64::MAX).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::MAX); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, 0); - }, - true, - ); - } - - #[test] - fn test_ge_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Ge, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - libc::ioctl(0, (KVM_GET_PIT2 + 1) as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, (KVM_GET_PIT2 - 1) as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Ge, u64::from(u32::MAX)).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX)); - libc::ioctl(0, 0, u64::from(u32::MAX) + 1); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, 1); - }, - true, - ); - } - - #[test] - fn test_gt_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Gt, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, (KVM_GET_PIT2 + 1) as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Gt, u64::from(u32::MAX) + 10).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 11); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 10); - }, - true, - ); - } - - #[test] - fn test_le_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Le, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - libc::ioctl(0, (KVM_GET_PIT2 - 1) as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, (KVM_GET_PIT2 + 1) as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Le, u64::from(u32::MAX) + 10).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 10); - libc::ioctl(0, 0, u64::from(u32::MAX) + 9); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 11); - }, - true, - ); - } - - #[test] - fn test_lt_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Lt, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, (KVM_GET_PIT2 - 1) as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Lt, u64::from(u32::MAX) + 10).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 9); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX) + 10); - }, - true, - ); - } - - #[test] - fn test_masked_eq_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new( - 1, - SeccompCmpArgLen::Dword, - MaskedEq(KVM_GET_PIT2_MSB), - KVM_GET_PIT2, - ) - .unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - libc::ioctl(0, KVM_GET_PIT2_MSB as IoctlRequest); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, KVM_GET_PIT2_LSB as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new( - 2, - SeccompCmpArgLen::Qword, - MaskedEq(u64::from(u32::MAX)), - u64::MAX, - ) - .unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, u64::from(u32::MAX)); - libc::ioctl(0, 0, u64::MAX); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, 0); - }, - true, - ); - } - - #[test] - fn test_ne_operator() { - // check use case for SeccompCmpArgLen::DWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(1, SeccompCmpArgLen::Dword, Ne, KVM_GET_PIT2).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, KVM_GET_PIT2 as IoctlRequest); - }, - true, - ); - - // check use case for SeccompCmpArgLen::QWORD - let rules = vec![allow_syscall_if( - libc::SYS_ioctl, - vec![SeccompRule::new( - vec![Cond::new(2, SeccompCmpArgLen::Qword, Ne, u64::MAX).unwrap()], - SeccompAction::Allow, - )], - )]; - // check syscalls that are supposed to work - validate_seccomp_filter( - rules.clone(), - || unsafe { - libc::ioctl(0, 0, 0); - }, - false, - ); - // check syscalls that are not supposed to work - validate_seccomp_filter( - rules, - || unsafe { - libc::ioctl(0, 0, u64::MAX); - }, - true, - ); - } - - // Checks that rule gets translated correctly into BPF statements. - #[test] - fn test_rule_bpf_output() { - Cond::new(6, ArgLen::Qword, Eq, 1).unwrap_err(); - - // Builds rule. - let rule = SeccompRule::new( - vec![ - Cond::new(0, ArgLen::Dword, Eq, 1).unwrap(), - Cond::new(2, ArgLen::Qword, MaskedEq(0b1010), 14).unwrap(), - ], - SeccompAction::Allow, - ); - - let (msb_offset, lsb_offset) = { (4, 0) }; - - // Builds hardcoded BPF instructions. - let instructions = vec![ - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 10), - BPF_STMT(0x20, 32 + msb_offset), - BPF_STMT(0x54, 0), - BPF_JUMP(0x15, 0, 0, 6), - BPF_STMT(0x20, 32 + lsb_offset), - BPF_STMT(0x54, 0b1010), - BPF_JUMP(0x15, 14 & 0b1010, 0, 3), - BPF_STMT(0x20, 16 + lsb_offset), - BPF_JUMP(0x15, 1, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - ]; - - // Compares translated rule with hardcoded BPF instructions. - let bpfprog: BpfProgram = rule.into(); - assert_eq!(bpfprog, instructions); - } - - // Checks that rule with too many conditions gets translated correctly into BPF statements - // using three helper jumps. - #[test] - fn test_rule_many_conditions_bpf_output() { - // Builds rule. - let mut conditions = Vec::with_capacity(43); - for _ in 0..42 { - conditions.push(Cond::new(0, ArgLen::Qword, MaskedEq(0), 0).unwrap()); - } - conditions.push(Cond::new(0, ArgLen::Qword, Eq, 0).unwrap()); - let rule = SeccompRule::new(conditions, SeccompAction::Allow); - - let (msb_offset, lsb_offset) = { (4, 0) }; - - // Builds hardcoded BPF instructions. - let mut instructions = vec![ - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 6), - BPF_STMT(0x20, 16 + msb_offset), - BPF_JUMP(0x15, 0, 0, 3), - BPF_STMT(0x20, 16 + lsb_offset), - BPF_JUMP(0x15, 0, 0, 1), - BPF_STMT(0x05, 2), - BPF_STMT(0x05, 254), - BPF_STMT(0x05, 254), - ]; - let mut offset = 253; - for _ in 0..42 { - offset -= 6; - instructions.append(&mut vec![ - BPF_STMT(0x20, 16 + msb_offset), - BPF_STMT(0x54, 0), - BPF_JUMP(0x15, 0, 0, offset + 3), - BPF_STMT(0x20, 16 + lsb_offset), - BPF_STMT(0x54, 0), - BPF_JUMP(0x15, 0, 0, offset), - ]); - } - instructions.push(BPF_STMT(0x06, 0x7fff_0000)); - - // Compares translated rule with hardcoded BPF instructions. - let bpfprog: BpfProgram = rule.into(); - assert_eq!(bpfprog, instructions); - } - - fn create_test_bpf_filter(arg_len: ArgLen) -> SeccompFilter { - SeccompFilter::new( - vec![ - allow_syscall_if( - 1, - vec![ - SeccompRule::new( - vec![ - Cond::new(2, arg_len.clone(), Le, 14).unwrap(), - Cond::new(2, arg_len.clone(), Ne, 10).unwrap(), - ], - SeccompAction::Allow, - ), - SeccompRule::new( - vec![ - Cond::new(2, arg_len.clone(), Gt, 20).unwrap(), - Cond::new(2, arg_len.clone(), Lt, 30).unwrap(), - ], - SeccompAction::Allow, - ), - SeccompRule::new( - vec![Cond::new(2, arg_len.clone(), Ge, 42).unwrap()], - SeccompAction::Allow, - ), - ], - ), - allow_syscall_if( - 9, - vec![SeccompRule::new( - vec![Cond::new(1, arg_len, MaskedEq(0b100), 36).unwrap()], - SeccompAction::Allow, - )], - ), - ] - .into_iter() - .collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap() - } - - #[test] - fn test_filter_bpf_output_dword() { - // Compares translated filter with hardcoded BPF program. - { - let mut empty_rule_map = BTreeMap::new(); - empty_rule_map.insert(1, vec![]); - SeccompFilter::new(empty_rule_map, SeccompAction::Allow, ARCH).unwrap_err(); - } - - let filter = create_test_bpf_filter(ArgLen::Dword); - - let mut instructions = Vec::new(); - instructions.extend(VALIDATE_ARCHITECTURE(ARCH.try_into().unwrap())); - instructions.extend(vec![ - BPF_STMT(0x20, 0), - BPF_JUMP(0x15, 1, 0, 1), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 6), - BPF_STMT(0x20, 32), - BPF_JUMP(0x15, 10, 3, 0), - BPF_STMT(0x20, 32), - BPF_JUMP(0x25, 14, 1, 0), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 6), - BPF_STMT(0x20, 32), - BPF_JUMP(0x35, 30, 3, 0), - BPF_STMT(0x20, 32), - BPF_JUMP(0x25, 20, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 4), - BPF_STMT(0x20, 32), - BPF_JUMP(0x35, 42, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x06, 0x0003_0000), - BPF_JUMP(0x15, 9, 0, 1), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 5), - BPF_STMT(0x20, 24), - BPF_STMT(0x54, 0b100), - BPF_JUMP(0x15, 36 & 0b100, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x06, 0x0003_0000), - BPF_STMT(0x06, 0x0003_0000), - ]); - - let bpfprog: BpfProgram = filter.try_into().unwrap(); - assert_eq!(bpfprog, instructions); - } - - #[test] - fn test_filter_bpf_output_qword() { - // Compares translated filter with hardcoded BPF program. - { - let mut empty_rule_map = BTreeMap::new(); - empty_rule_map.insert(1, vec![]); - SeccompFilter::new(empty_rule_map, SeccompAction::Allow, ARCH).unwrap_err(); - } - - let filter = create_test_bpf_filter(ArgLen::Qword); - - let mut instructions = Vec::new(); - instructions.extend(VALIDATE_ARCHITECTURE(ARCH.try_into().unwrap())); - instructions.extend(vec![ - BPF_STMT(0x20, 0), - BPF_JUMP(0x15, 1, 0, 1), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 11), - BPF_STMT(0x20, 36), - BPF_JUMP(0x15, 0, 0, 2), - BPF_STMT(0x20, 32), - BPF_JUMP(0x15, 10, 6, 0), - BPF_STMT(0x20, 36), - BPF_JUMP(0x25, 0, 4, 0), - BPF_JUMP(0x15, 0, 0, 2), - BPF_STMT(0x20, 32), - BPF_JUMP(0x25, 14, 1, 0), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 12), - BPF_STMT(0x20, 36), - BPF_JUMP(0x25, 0, 9, 0), - BPF_JUMP(0x15, 0, 0, 2), - BPF_STMT(0x20, 32), - BPF_JUMP(0x35, 30, 6, 0), - BPF_STMT(0x20, 36), - BPF_JUMP(0x25, 0, 3, 0), - BPF_JUMP(0x15, 0, 0, 3), - BPF_STMT(0x20, 32), - BPF_JUMP(0x25, 20, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 7), - BPF_STMT(0x20, 36), - BPF_JUMP(0x25, 0, 3, 0), - BPF_JUMP(0x15, 0, 0, 3), - BPF_STMT(0x20, 32), - BPF_JUMP(0x35, 42, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x06, 0x0003_0000), - BPF_JUMP(0x15, 9, 0, 1), - BPF_STMT(0x05, 1), - BPF_STMT(0x05, 8), - BPF_STMT(0x20, 28), - BPF_STMT(0x54, 0), - BPF_JUMP(0x15, 0, 0, 4), - BPF_STMT(0x20, 24), - BPF_STMT(0x54, 0b100), - BPF_JUMP(0x15, 36 & 0b100, 0, 1), - BPF_STMT(0x06, 0x7fff_0000), - BPF_STMT(0x06, 0x0003_0000), - BPF_STMT(0x06, 0x0003_0000), - ]); - - let bpfprog: BpfProgram = filter.try_into().unwrap(); - assert_eq!(bpfprog, instructions); - } - - #[test] - fn test_bpf_expanding_functions() { - // Compares the output of the BPF instruction generating functions to hardcoded - // instructions. - assert_eq!( - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 16), - sock_filter { - code: 0x20, - jt: 0, - jf: 0, - k: 16, - } - ); - assert_eq!( - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 10, 2, 5), - sock_filter { - code: 0x15, - jt: 2, - jf: 5, - k: 10, - } - ); - } - - #[test] - fn test_bpf_functions() { - { - let ret = VALIDATE_ARCHITECTURE(ARCH.try_into().unwrap()); - let instructions = vec![ - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 4, - }, - sock_filter { - code: 21, - jt: 1, - jf: 0, - #[cfg(target_arch = "x86_64")] - k: AUDIT_ARCH_X86_64, - #[cfg(target_arch = "aarch64")] - k: AUDIT_ARCH_AARCH64, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: SECCOMP_RET_KILL_PROCESS, - }, - ]; - assert_eq!(ret, instructions); - } - - { - let ret = EXAMINE_SYSCALL(); - let instructions = vec![sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 0, - }]; - assert_eq!(ret, instructions); - } - } - - #[test] - fn test_empty_filter() { - // An empty filter should always return the default action. - // For example, for an empty allowlist, it should always trap/kill, - // for an empty denylist, it should allow allow all system calls. - - let mut expected_program = Vec::new(); - expected_program.extend(VALIDATE_ARCHITECTURE(ARCH.try_into().unwrap())); - expected_program.extend(vec![BPF_STMT(0x06, 0x7fff_0000)]); - - let empty_rule_map = BTreeMap::new(); - let filter = SeccompFilter::new(empty_rule_map, SeccompAction::Allow, ARCH).unwrap(); - let prog: BpfProgram = filter.try_into().unwrap(); - - assert_eq!(expected_program, prog); - - // This should allow any system calls. - let pid = thread::spawn(move || { - // Install the filter. - install_filter(prog); - - unsafe { libc::getpid() } - }) - .join() - .unwrap(); - - // Check that the getpid syscall returned successfully. - assert!(pid > 0); - } - - #[test] - fn test_error_messages() { - assert_eq!( - format!("{}", FilterError::EmptyRulesVector), - "The seccomp rules vector is empty." - ); - assert_eq!( - format!("{}", FilterError::FilterTooLarge), - "The seccomp filter contains too many BPF instructions." - ); - assert_eq!( - format!("{}", FilterError::InvalidArgumentNumber), - "The seccomp rule contains an invalid argument number." - ); - assert_eq!( - format!( - "{}", - FilterError::Arch(TargetArchError::InvalidString("lala".to_string())) - ), - format!("{0}", TargetArchError::InvalidString("lala".to_string())) - ); - } - - #[test] - fn test_from_seccomp_action() { - assert_eq!(0x7fff_0000, u32::from(SeccompAction::Allow)); - assert_eq!(0x0005_002a, u32::from(SeccompAction::Errno(42))); - assert_eq!(0x0000_0000, u32::from(SeccompAction::KillThread)); - assert_eq!(0x8000_0000, u32::from(SeccompAction::KillProcess)); - assert_eq!(0x7ffc_0000, u32::from(SeccompAction::Log)); - assert_eq!(0x7ff0_002a, u32::from(SeccompAction::Trace(42))); - assert_eq!(0x0003_0000, u32::from(SeccompAction::Trap)); - } - - #[test] - fn test_validate_condition() { - // Invalid argument number - assert_eq!( - Cond::new(90, ArgLen::Dword, Eq, 65), - Err(FilterError::InvalidArgumentNumber) - ); - - // Valid argument number - Cond::new(0, ArgLen::Dword, Eq, 65).unwrap(); - } - - #[test] - fn test_seccomp_filter_validate() { - // Failure cases. - { - // Syscall has no rules. - assert_eq!( - SeccompFilter::new( - vec![(1, vec![]),].into_iter().collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap_err(), - FilterError::EmptyRulesVector - ); - // Syscall has multiple empty rules. - assert_eq!( - SeccompFilter::new( - vec![( - 1, - vec![ - SeccompRule::new(vec![], SeccompAction::Allow), - SeccompRule::new(vec![], SeccompAction::Allow) - ] - ),] - .into_iter() - .collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap_err(), - FilterError::ConflictingRules(1) - ); - - // Syscall has both empty rules condition-based rules. - assert_eq!( - SeccompFilter::new( - vec![( - 1, - vec![ - SeccompRule::new(vec![], SeccompAction::Allow), - SeccompRule::new( - vec![ - Cond::new(2, ArgLen::Dword, Le, 14).unwrap(), - Cond::new(1, ArgLen::Dword, Ne, 10).unwrap(), - ], - SeccompAction::Allow, - ), - ] - ),] - .into_iter() - .collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap_err(), - FilterError::ConflictingRules(1) - ); - } - } -} diff --git a/src/seccompiler/src/bin.rs b/src/seccompiler/src/bin.rs new file mode 100644 index 00000000000..8fb9d0fd511 --- /dev/null +++ b/src/seccompiler/src/bin.rs @@ -0,0 +1,40 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use seccompiler::{compile_bpf, CompilationError}; + +const DEFAULT_OUTPUT_FILENAME: &str = "seccomp_binary_filter.out"; + +#[derive(Debug, Parser)] +#[command(version = format!("v{}", env!("CARGO_PKG_VERSION")))] +struct Cli { + #[arg( + short, + long, + help = "The computer architecture where the BPF program runs. Supported architectures: \ + x86_64, aarch64." + )] + target_arch: String, + #[arg(short, long, help = "File path of the JSON input.")] + input_file: String, + #[arg(short, long, help = "Optional path of the output file.", default_value = DEFAULT_OUTPUT_FILENAME)] + output_file: String, + #[arg( + short, + long, + help = "Deprecated! Transforms the filters into basic filters. Drops all argument checks \ + and rule-level actions. Not recommended." + )] + basic: bool, +} + +fn main() -> Result<(), CompilationError> { + let cli = Cli::parse(); + compile_bpf( + &cli.input_file, + &cli.target_arch, + &cli.output_file, + cli.basic, + ) +} diff --git a/src/seccompiler/src/bindings.rs b/src/seccompiler/src/bindings.rs new file mode 100644 index 00000000000..969ea91cd1c --- /dev/null +++ b/src/seccompiler/src/bindings.rs @@ -0,0 +1,171 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2021 Sony Group Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +//! Raw FFI bindings for libseccomp library + +use std::os::raw::*; + +pub const MINUS_EEXIST: i32 = -libc::EEXIST; + +/// Filter context/handle (`*mut`) +pub type scmp_filter_ctx = *mut c_void; +/// Filter context/handle (`*const`) +pub type const_scmp_filter_ctx = *const c_void; + +/// Comparison operators +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(C)] +pub enum scmp_compare { + _SCMP_CMP_MIN = 0, + /// not equal + SCMP_CMP_NE = 1, + /// less than + SCMP_CMP_LT = 2, + /// less than or equal + SCMP_CMP_LE = 3, + /// equal + SCMP_CMP_EQ = 4, + /// greater than or equal + SCMP_CMP_GE = 5, + /// greater than + SCMP_CMP_GT = 6, + /// masked equality + SCMP_CMP_MASKED_EQ = 7, + _SCMP_CMP_MAX, +} + +/// Argument datum +pub type scmp_datum_t = u64; + +/// Argument / Value comparison definition +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(C)] +pub struct scmp_arg_cmp { + /// argument number, starting at 0 + pub arg: c_uint, + /// the comparison op, e.g. `SCMP_CMP_*` + pub op: scmp_compare, + pub datum_a: scmp_datum_t, + pub datum_b: scmp_datum_t, +} + +pub const SCMP_ARCH_X86_64: u32 = 0xc000003e; +pub const SCMP_ARCH_AARCH64: u32 = 0xc00000b7; +/// Kill the process +pub const SCMP_ACT_KILL_PROCESS: u32 = 0x80000000; +/// Kill the thread +pub const SCMP_ACT_KILL_THREAD: u32 = 0x00000000; +/// Throw a `SIGSYS` signal +pub const SCMP_ACT_TRAP: u32 = 0x00030000; +/// Notifies userspace +pub const SCMP_ACT_ERRNO_MASK: u32 = 0x00050000; +/// Return the specified error code +#[must_use] +pub const fn SCMP_ACT_ERRNO(x: u16) -> u32 { + SCMP_ACT_ERRNO_MASK | x as u32 +} +pub const SCMP_ACT_TRACE_MASK: u32 = 0x7ff00000; +/// Notify a tracing process with the specified value +#[must_use] +pub const fn SCMP_ACT_TRACE(x: u16) -> u32 { + SCMP_ACT_TRACE_MASK | x as u32 +} +/// Allow the syscall to be executed after the action has been logged +pub const SCMP_ACT_LOG: u32 = 0x7ffc0000; +/// Allow the syscall to be executed +pub const SCMP_ACT_ALLOW: u32 = 0x7fff0000; + +#[link(name = "seccomp")] +unsafe extern "C" { + /// Initialize the filter state + /// + /// - `def_action`: the default filter action + /// + /// This function initializes the internal seccomp filter state and should + /// be called before any other functions in this library to ensure the filter + /// state is initialized. Returns a filter context on success, `ptr::null()` on failure. + pub safe fn seccomp_init(def_action: u32) -> scmp_filter_ctx; + + /// Adds an architecture to the filter + /// + /// - `ctx`: the filter context + /// - `arch_token`: the architecture token, e.g. `SCMP_ARCH_*` + /// + /// This function adds a new architecture to the given seccomp filter context. + /// Any new rules added after this function successfully returns will be added + /// to this architecture but existing rules will not be added to this + /// architecture. If the architecture token is [`SCMP_ARCH_NATIVE`] then the native + /// architecture will be assumed. Returns zero on success, `-libc::EEXIST` if + /// specified architecture is already present, other negative values on failure. + pub fn seccomp_arch_add(ctx: scmp_filter_ctx, arch_token: u32) -> c_int; + + /// Resolve a syscall name to a number + /// + /// - `name`: the syscall name + /// + /// Resolve the given syscall name to the syscall number. Returns the syscall + /// number on success, including negative pseudo syscall numbers (e.g. `__PNR_*`); + /// returns [`__NR_SCMP_ERROR`] on failure. + pub fn seccomp_syscall_resolve_name(name: *const c_char) -> c_int; + + /// Add a new rule to the filter + /// + /// - `ctx`: the filter context + /// - `action`: the filter action + /// - `syscall`: the syscall number + /// - `arg_cnt`: the number of argument filters in the argument filter chain + /// - `...`: [`scmp_arg_cmp`] structs + /// + /// This function adds a series of new argument/value checks to the seccomp + /// filter for the given syscall; multiple argument/value checks can be + /// specified and they will be chained together (AND'd together) in the filter. + /// If the specified rule needs to be adjusted due to architecture specifics it + /// will be adjusted without notification. Returns zero on success, negative + /// values on failure. + pub fn seccomp_rule_add( + ctx: scmp_filter_ctx, + action: u32, + syscall: c_int, + arg_cnt: c_uint, + ... + ) -> c_int; + + /// Add a new rule to the filter + /// + /// - `ctx`: the filter context + /// - `action`: the filter action + /// - `syscall`: the syscall number + /// - `arg_cnt`: the number of elements in the arg_array parameter + /// - `arg_array`: array of [`scmp_arg_cmp`] structs + /// + /// This function adds a series of new argument/value checks to the seccomp + /// filter for the given syscall; multiple argument/value checks can be + /// specified and they will be chained together (AND'd together) in the filter. + /// If the specified rule needs to be adjusted due to architecture specifics it + /// will be adjusted without notification. Returns zero on success, negative + /// values on failure. + pub fn seccomp_rule_add_array( + ctx: scmp_filter_ctx, + action: u32, + syscall: c_int, + arg_cnt: c_uint, + arg_array: *const scmp_arg_cmp, + ) -> c_int; + + /// Generate seccomp Berkeley Packet Filter (BPF) code and export it to a file + /// + /// - `ctx`: the filter context + /// - `fd`: the destination fd + /// + /// This function generates seccomp Berkeley Packer Filter (BPF) code and writes + /// it to the given fd. Returns zero on success, negative values on failure. + pub fn seccomp_export_bpf(ctx: const_scmp_filter_ctx, fd: c_int) -> c_int; +} + +/// Negative pseudo syscall number returned by some functions in case of an error +pub const __NR_SCMP_ERROR: c_int = -1; diff --git a/src/seccompiler/src/common.rs b/src/seccompiler/src/common.rs deleted file mode 100644 index 80ff96ad9f3..00000000000 --- a/src/seccompiler/src/common.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -//! Module that defines common data structures used by both the library crate -//! and seccompiler-bin. - -use serde::{Deserialize, Serialize}; - -/// The maximum seccomp-BPF program length allowed by the linux kernel. -pub const BPF_MAX_LEN: u16 = 4096; - -/// BPF instruction structure definition. -/// See /usr/include/linux/filter.h . -#[repr(C)] -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -#[doc(hidden)] -pub struct sock_filter { - pub code: ::std::os::raw::c_ushort, - pub jt: ::std::os::raw::c_uchar, - pub jf: ::std::os::raw::c_uchar, - pub k: ::std::os::raw::c_uint, -} - -/// Program made up of a sequence of BPF instructions. -pub type BpfProgram = Vec; diff --git a/src/seccompiler/src/compiler.rs b/src/seccompiler/src/compiler.rs deleted file mode 100644 index 9194bc7e5bd..00000000000 --- a/src/seccompiler/src/compiler.rs +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -//! Module defining the logic for compiling the deserialized filter objects into the IR. -//! Used by seccompiler-bin. -//! -//! Via the `Compiler::compile_blob()` method, it also drives the entire JSON -> BLOB -//! transformation process. -//! -//! It also defines some of the objects that a JSON seccomp filter is deserialized into: -//! [`Filter`](struct.Filter.html), -//! [`SyscallRule`](struct.SyscallRule.html). -// -//! The rest of objects are deserialized directly into the IR (intermediate representation): -//! [`SeccompCondition`](../backend/struct.SeccompCondition.html), -//! [`SeccompAction`](../backend/enum.SeccompAction.html), -//! [`SeccompCmpOp`](../backend/enum.SeccompCmpOp.html), -//! [`SeccompCmpArgLen`](../backend/enum.SeccompCmpArgLen.html). - -use std::collections::BTreeMap; -use std::convert::{Into, TryInto}; -use std::{fmt, result}; - -use serde::de::{self, Error as _, MapAccess, Visitor}; -use serde::Deserialize; - -use crate::backend::{ - Comment, FilterError, SeccompAction, SeccompCondition, SeccompFilter, SeccompRule, - SeccompRuleMap, TargetArch, -}; -use crate::common::BpfProgram; -use crate::syscall_table::SyscallTable; - -/// Errors compiling Filters into BPF. -#[derive(Debug, PartialEq, thiserror::Error, displaydoc::Display)] -pub enum CompilationError { - /// `filter_action` and `default_action` are equal. - IdenticalActions, - /// {0} - Filter(#[from] FilterError), - /// Invalid syscall name: {0} for given arch: {1:?}. - SyscallName(String, TargetArch), -} - -/// Deserializable object that represents the Json filter file. -#[derive(Debug)] -pub struct JsonFile(pub BTreeMap); - -// Implement a custom deserializer, that returns an error for duplicate thread keys. -impl<'de> Deserialize<'de> for JsonFile { - fn deserialize(deserializer: D) -> result::Result - where - D: de::Deserializer<'de>, - { - #[derive(Debug)] - struct JsonFileVisitor; - - impl<'d> Visitor<'d> for JsonFileVisitor { - type Value = BTreeMap; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { - f.write_str("a map of filters") - } - - fn visit_map(self, mut access: M) -> result::Result - where - M: MapAccess<'d>, - { - let mut values = Self::Value::new(); - - while let Some((key, value)) = access.next_entry()? { - if values.insert(key, value).is_some() { - return Err(M::Error::custom("duplicate filter key")); - }; - } - - Ok(values) - } - } - Ok(JsonFile(deserializer.deserialize_map(JsonFileVisitor)?)) - } -} - -/// Deserializable object representing a syscall rule. -#[derive(Debug, Deserialize, PartialEq, Clone)] -#[serde(deny_unknown_fields)] -pub struct SyscallRule { - /// Name of the syscall. - syscall: String, - /// Rule conditions. - #[serde(rename = "args")] - conditions: Option>, - /// Optional empty value, represents a `comment` property in the JSON file. - comment: Option, -} - -impl SyscallRule { - /// Perform semantic checks after deserialization. - fn validate(&self) -> Result<(), CompilationError> { - // Validate all `SeccompCondition`s. - if let Some(conditions) = self.conditions.as_ref() { - return conditions - .iter() - .filter_map(|cond| cond.validate().err()) - .next() - .map_or(Ok(()), |err| Err(CompilationError::Filter(err))); - } - - Ok(()) - } -} - -/// Deserializable seccomp filter. Refers to one thread category. -#[derive(Deserialize, PartialEq, Debug, Clone)] -#[serde(deny_unknown_fields)] -pub struct Filter { - /// Default action if no rules match. e.g. `Kill` for an AllowList. - default_action: SeccompAction, - /// Default action if a rule matches. e.g. `Allow` for an AllowList. - filter_action: SeccompAction, - /// The collection of `SyscallRule`s. - filter: Vec, -} - -impl Filter { - /// Perform semantic checks after deserialization. - fn validate(&self) -> Result<(), CompilationError> { - // Doesn't make sense to have equal default and on-match actions. - if self.default_action == self.filter_action { - return Err(CompilationError::IdenticalActions); - } - - // Validate all `SyscallRule`s. - self.filter - .iter() - .filter_map(|syscall_rule| syscall_rule.validate().err()) - .next() - .map_or(Ok(()), Err) - } -} - -/// Object responsible for compiling [`Filter`](struct.Filter.html)s into -/// [`BpfProgram`](../common/type.BpfProgram.html)s. -/// Uses the [`SeccompFilter`](../backend/struct.SeccompFilter.html) interface as an IR language. -#[derive(Debug)] -pub struct Compiler { - /// Target architecture. Can be different from the current `target_arch`. - arch: TargetArch, - /// Target-specific syscall table. - syscall_table: SyscallTable, -} - -impl Compiler { - /// Create a new `Compiler` instance, for the given target architecture. - pub fn new(arch: TargetArch) -> Self { - Self { - arch, - syscall_table: SyscallTable::new(arch), - } - } - - /// Perform semantic checks after deserialization. - fn validate_filters(&self, filters: &BTreeMap) -> Result<(), CompilationError> { - // Validate all `Filter`s. - filters - .iter() - .filter_map(|(_, filter)| filter.validate().err()) - .next() - .map_or(Ok(()), Err) - } - - /// Main compilation function. - pub fn compile_blob( - &self, - filters: BTreeMap, - is_basic: bool, - ) -> Result, CompilationError> { - self.validate_filters(&filters)?; - let mut bpf_map: BTreeMap = BTreeMap::new(); - - for (thread_name, filter) in filters.into_iter() { - if is_basic { - bpf_map.insert( - thread_name, - self.make_basic_seccomp_filter(filter)?.try_into()?, - ); - } else { - bpf_map.insert(thread_name, self.make_seccomp_filter(filter)?.try_into()?); - } - } - Ok(bpf_map) - } - - /// Transforms the deserialized `Filter` into a `SeccompFilter` (IR language). - fn make_seccomp_filter(&self, filter: Filter) -> Result { - let mut rule_map: SeccompRuleMap = SeccompRuleMap::new(); - let filter_action = &filter.filter_action; - - for syscall_rule in filter.filter { - let syscall_name = syscall_rule.syscall; - let action = filter_action.clone(); - let syscall_nr = self - .syscall_table - .get_syscall_nr(&syscall_name) - .ok_or_else(|| CompilationError::SyscallName(syscall_name.clone(), self.arch))?; - let rule_accumulator = rule_map.entry(syscall_nr).or_default(); - - match syscall_rule.conditions { - Some(conditions) => rule_accumulator.push(SeccompRule::new(conditions, action)), - None => rule_accumulator.push(SeccompRule::new(vec![], action)), - }; - } - - SeccompFilter::new(rule_map, filter.default_action, self.arch.into()) - .map_err(CompilationError::Filter) - } - - /// Transforms the deserialized `Filter` into a basic `SeccompFilter` (IR language). - /// This filter will drop any argument checks and any rule-level action. - /// All rules will trigger the filter-level `filter_action`. - fn make_basic_seccomp_filter(&self, filter: Filter) -> Result { - let mut rule_map: SeccompRuleMap = SeccompRuleMap::new(); - let filter_action = &filter.filter_action; - - for syscall_rule in filter.filter { - let syscall_name = syscall_rule.syscall; - // Basic filters bypass the rule-level action and use the filter_action. - let action = filter_action.clone(); - let syscall_nr = self - .syscall_table - .get_syscall_nr(&syscall_name) - .ok_or_else(|| CompilationError::SyscallName(syscall_name.clone(), self.arch))?; - - // If there is already an entry for this syscall, do nothing. - // Otherwise, insert an empty rule that triggers the filter_action. - rule_map - .entry(syscall_nr) - .or_insert_with(|| vec![SeccompRule::new(vec![], action)]); - } - - SeccompFilter::new(rule_map, filter.default_action, self.arch.into()) - .map_err(CompilationError::Filter) - } -} - -#[cfg(test)] -mod tests { - use std::collections::BTreeMap; - use std::convert::TryInto; - use std::env::consts::ARCH; - - use super::{CompilationError, Compiler, Filter, SyscallRule}; - use crate::backend::SeccompCmpArgLen::*; - use crate::backend::SeccompCmpOp::*; - use crate::backend::{ - FilterError, SeccompAction, SeccompCondition as Cond, SeccompFilter, SeccompRule, - TargetArch, - }; - - impl Filter { - fn new( - default_action: SeccompAction, - filter_action: SeccompAction, - filter: Vec, - ) -> Filter { - Filter { - default_action, - filter_action, - filter, - } - } - } - - impl SyscallRule { - fn new(syscall: String, conditions: Option>) -> SyscallRule { - SyscallRule { - syscall, - conditions, - comment: None, - } - } - } - - fn match_syscall(syscall_number: i64, action: SeccompAction) -> (i64, Vec) { - (syscall_number, vec![SeccompRule::new(vec![], action)]) - } - - fn match_syscall_if(syscall_number: i64, rules: Vec) -> (i64, Vec) { - (syscall_number, rules) - } - - #[test] - // Test the transformation of Filter objects into SeccompFilter objects. - // We test this private method because we are interested in seeing that the - // Filter -> SeccompFilter transformation is done correctly. - fn test_make_seccomp_filter() { - let compiler = Compiler::new(ARCH.try_into().unwrap()); - // Test a well-formed filter. Malformed filters are tested in test_compile_blob(). - let filter = Filter::new( - SeccompAction::Trap, - SeccompAction::Allow, - vec![ - SyscallRule::new("read".to_string(), None), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(2, Dword, Le, 65).unwrap(), - Cond::new(1, Qword, Ne, 80).unwrap(), - ]), - ), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(3, Qword, Gt, 65).unwrap(), - Cond::new(1, Qword, Lt, 80).unwrap(), - ]), - ), - SyscallRule::new( - "futex".to_string(), - Some(vec![Cond::new(3, Qword, Ge, 65).unwrap()]), - ), - SyscallRule::new( - "ioctl".to_string(), - Some(vec![Cond::new(3, Dword, MaskedEq(100), 65).unwrap()]), - ), - ], - ); - - // The expected IR. - let seccomp_filter = SeccompFilter::new( - vec![ - match_syscall( - compiler.syscall_table.get_syscall_nr("read").unwrap(), - SeccompAction::Allow, - ), - match_syscall_if( - compiler.syscall_table.get_syscall_nr("futex").unwrap(), - vec![ - SeccompRule::new( - vec![ - Cond::new(2, Dword, Le, 65).unwrap(), - Cond::new(1, Qword, Ne, 80).unwrap(), - ], - SeccompAction::Allow, - ), - SeccompRule::new( - vec![ - Cond::new(3, Qword, Gt, 65).unwrap(), - Cond::new(1, Qword, Lt, 80).unwrap(), - ], - SeccompAction::Allow, - ), - SeccompRule::new( - vec![Cond::new(3, Qword, Ge, 65).unwrap()], - SeccompAction::Allow, - ), - ], - ), - match_syscall_if( - compiler.syscall_table.get_syscall_nr("ioctl").unwrap(), - vec![SeccompRule::new( - vec![Cond::new(3, Dword, MaskedEq(100), 65).unwrap()], - SeccompAction::Allow, - )], - ), - ] - .into_iter() - .collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap(); - - assert_eq!( - compiler.make_seccomp_filter(filter).unwrap(), - seccomp_filter - ); - } - - #[test] - // Test the transformation of Filter objects into SeccompFilter objects. - // This `basic` alternative version of the make_seccomp_filter method drops argument checks. - fn test_make_basic_seccomp_filter() { - let compiler = Compiler::new(ARCH.try_into().unwrap()); - // Test a well-formed filter. Malformed filters are tested in test_compile_blob(). - let filter = Filter::new( - SeccompAction::Trap, - SeccompAction::Allow, - vec![ - SyscallRule::new("read".to_string(), None), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(2, Dword, Le, 65).unwrap(), - Cond::new(1, Qword, Ne, 80).unwrap(), - ]), - ), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(3, Qword, Gt, 65).unwrap(), - Cond::new(1, Qword, Lt, 80).unwrap(), - ]), - ), - SyscallRule::new( - "futex".to_string(), - Some(vec![Cond::new(3, Qword, Ge, 65).unwrap()]), - ), - SyscallRule::new( - "ioctl".to_string(), - Some(vec![Cond::new(3, Dword, MaskedEq(100), 65).unwrap()]), - ), - ], - ); - - // The expected IR. - let seccomp_filter = SeccompFilter::new( - vec![ - match_syscall( - compiler.syscall_table.get_syscall_nr("read").unwrap(), - SeccompAction::Allow, - ), - match_syscall( - compiler.syscall_table.get_syscall_nr("futex").unwrap(), - SeccompAction::Allow, - ), - match_syscall( - compiler.syscall_table.get_syscall_nr("ioctl").unwrap(), - SeccompAction::Allow, - ), - ] - .into_iter() - .collect(), - SeccompAction::Trap, - ARCH, - ) - .unwrap(); - - assert_eq!( - compiler.make_basic_seccomp_filter(filter).unwrap(), - seccomp_filter - ); - } - - #[test] - fn test_compile_blob() { - let compiler = Compiler::new(ARCH.try_into().unwrap()); - // Test with malformed filters. - - let mut wrong_syscall_name_filters = BTreeMap::new(); - wrong_syscall_name_filters.insert( - "T1".to_string(), - Filter::new( - SeccompAction::Trap, - SeccompAction::Allow, - vec![SyscallRule::new("wrong_syscall".to_string(), None)], - ), - ); - - assert_eq!( - compiler.compile_blob(wrong_syscall_name_filters, false), - Err(CompilationError::SyscallName( - "wrong_syscall".to_string(), - compiler.arch - )) - ); - - let mut identical_action_filters = BTreeMap::new(); - identical_action_filters.insert( - "T1".to_string(), - Filter::new(SeccompAction::Allow, SeccompAction::Allow, vec![]), - ); - - assert_eq!( - compiler.compile_blob(identical_action_filters, false), - Err(CompilationError::IdenticalActions) - ); - - // Test with correct filters. - let mut correct_filters = BTreeMap::new(); - correct_filters.insert( - "Thread1".to_string(), - Filter::new( - SeccompAction::Trap, - SeccompAction::Allow, - vec![ - SyscallRule::new("read".to_string(), None), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(1, Dword, Eq, 65).unwrap(), - Cond::new(2, Qword, Le, 80).unwrap(), - ]), - ), - SyscallRule::new( - "futex".to_string(), - Some(vec![ - Cond::new(3, Dword, Eq, 65).unwrap(), - Cond::new(2, Qword, Le, 80).unwrap(), - ]), - ), - ], - ), - ); - - // We don't test the BPF compilation in this module. - // This is done in the seccomp/lib.rs module. - // Here, we only test the (Filter -> SeccompFilter) transformations. (High-level -> IR) - compiler - .compile_blob(correct_filters.clone(), false) - .unwrap(); - // Also test with basic filtering on. - compiler.compile_blob(correct_filters, true).unwrap(); - } - - #[test] - fn test_error_messages() { - assert_eq!( - format!("{}", CompilationError::IdenticalActions), - "`filter_action` and `default_action` are equal." - ); - assert_eq!( - format!( - "{}", - CompilationError::Filter(FilterError::InvalidArgumentNumber) - ), - "The seccomp rule contains an invalid argument number." - ); - assert_eq!( - format!( - "{}", - CompilationError::SyscallName("asdsad".to_string(), TargetArch::x86_64) - ), - format!( - "Invalid syscall name: {} for given arch: {}.", - "asdsad", "x86_64" - ) - ); - } -} diff --git a/src/seccompiler/src/lib.rs b/src/seccompiler/src/lib.rs index cc3e4756996..3fd62106275 100644 --- a/src/seccompiler/src/lib.rs +++ b/src/seccompiler/src/lib.rs @@ -1,270 +1,181 @@ -// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#![warn(missing_docs)] - -//! The library crate that defines common helper functions that are generally used in -//! conjunction with seccompiler-bin. - -pub mod backend; -pub mod common; -pub mod compiler; -/// Syscall tables -pub mod syscall_table; - use std::collections::HashMap; -use std::fmt::Debug; -use std::io::Read; -use std::sync::Arc; +use std::fs::File; +use std::io::{Read, Seek}; +use std::os::fd::{AsRawFd, FromRawFd}; +use std::os::unix::fs::MetadataExt; +use std::str::FromStr; -use bincode::{DefaultOptions, Error as BincodeError, Options}; -use common::BPF_MAX_LEN; -// Re-export the data types needed for calling the helper functions. -pub use common::{sock_filter, BpfProgram}; +use bincode::Error as BincodeError; -/// Type that associates a thread category to a BPF program. -pub type BpfThreadMap = HashMap>; +mod bindings; +use bindings::*; -// BPF structure definition for filter array. -// See /usr/include/linux/filter.h . -#[repr(C)] -struct sock_fprog { - pub len: ::std::os::raw::c_ushort, - pub filter: *const sock_filter, -} - -/// Reference to program made up of a sequence of BPF instructions. -pub type BpfProgramRef<'a> = &'a [sock_filter]; +pub mod types; +pub use types::*; +use zerocopy::IntoBytes; -/// Binary filter deserialization errors. +/// Binary filter compilation errors. #[derive(Debug, thiserror::Error, displaydoc::Display)] -pub enum DeserializationError { - /// Bincode deserialization failed: {0} - Bincode(BincodeError), +pub enum CompilationError { + /// Cannot open input file: {0} + IntputOpen(std::io::Error), + /// Cannot read input file: {0} + InputRead(std::io::Error), + /// Cannot deserialize json: {0} + JsonDeserialize(serde_json::Error), + /// Cannot parse arch: {0} + ArchParse(String), + /// Cannot create libseccomp context + LibSeccompContext, + /// Cannot add libseccomp arch + LibSeccompArch, + /// Cannot add libseccomp syscall + LibSeccompSycall, + /// Cannot add libseccomp syscall rule + LibSeccompRule, + /// Cannot export libseccomp bpf + LibSeccompExport, + /// Cannot create memfd: {0} + MemfdCreate(std::io::Error), + /// Cannot rewind memfd: {0} + MemfdRewind(std::io::Error), + /// Cannot read from memfd: {0} + MemfdRead(std::io::Error), + /// Cannot create output file: {0} + OutputCreate(std::io::Error), + /// Cannot serialize bfp: {0} + BincodeSerialize(BincodeError), } -/// Filter installation errors. -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] -pub enum InstallationError { - /// Filter length exceeds the maximum size of {BPF_MAX_LEN:} instructions - FilterTooLarge, - /// prctl` syscall failed with error code: {0} - Prctl(i32), -} - -/// Deserialize a BPF file into a collection of usable BPF filters. -/// Has an optional `bytes_limit` that is passed to bincode to constrain the maximum amount of -/// memory that we can allocate while performing the deserialization. -/// It's recommended that the integrator of the library uses this to prevent memory allocations -/// DOS-es. -pub fn deserialize_binary( - reader: R, - bytes_limit: Option, -) -> std::result::Result { - let result = match bytes_limit { - // Also add the default options. These are not part of the `DefaultOptions` as per - // this issue: https://github.com/servo/bincode/issues/333 - Some(limit) => DefaultOptions::new() - .with_fixint_encoding() - .allow_trailing_bytes() - .with_limit(limit) - .deserialize_from::>(reader), - // No limit is the default. - None => bincode::deserialize_from::>(reader), - }; - - Ok(result - .map_err(DeserializationError::Bincode)? - .into_iter() - .map(|(k, v)| (k.to_lowercase(), Arc::new(v))) - .collect()) -} - -/// Helper function for installing a BPF filter. -pub fn apply_filter(bpf_filter: BpfProgramRef) -> std::result::Result<(), InstallationError> { - // If the program is empty, don't install the filter. - if bpf_filter.is_empty() { - return Ok(()); - } +pub fn compile_bpf( + input_path: &str, + arch: &str, + out_path: &str, + basic: bool, +) -> Result<(), CompilationError> { + let mut file_content = String::new(); + File::open(input_path) + .map_err(CompilationError::IntputOpen)? + .read_to_string(&mut file_content) + .map_err(CompilationError::InputRead)?; + let bpf_map_json: BpfJson = + serde_json::from_str(&file_content).map_err(CompilationError::JsonDeserialize)?; + + let arch = TargetArch::from_str(arch).map_err(CompilationError::ArchParse)?; - // If the program length is greater than the limit allowed by the kernel, - // fail quickly. Otherwise, `prctl` will give a more cryptic error code. - let bpf_filter_len = - u16::try_from(bpf_filter.len()).map_err(|_| InstallationError::FilterTooLarge)?; - if bpf_filter_len > BPF_MAX_LEN { - return Err(InstallationError::FilterTooLarge); + // SAFETY: Safe because the parameters are valid. + let memfd_fd = unsafe { libc::memfd_create(c"bpf".as_ptr().cast(), 0) }; + if memfd_fd < 0 { + return Err(CompilationError::MemfdCreate( + std::io::Error::last_os_error(), + )); } // SAFETY: Safe because the parameters are valid. - unsafe { - { - let rc = libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); - if rc != 0 { - return Err(InstallationError::Prctl(*libc::__errno_location())); + let mut memfd = unsafe { File::from_raw_fd(memfd_fd) }; + + let mut bpf_map: HashMap> = HashMap::new(); + for (name, filter) in bpf_map_json.0.iter() { + let default_action = filter.default_action.to_scmp_type(); + let filter_action = filter.filter_action.to_scmp_type(); + + // SAFETY: Safe as all args are correct. + let bpf_filter = { + let r = seccomp_init(default_action); + if r.is_null() { + return Err(CompilationError::LibSeccompContext); } - } - - let bpf_prog = sock_fprog { - len: bpf_filter_len, - filter: bpf_filter.as_ptr(), + r }; - let bpf_prog_ptr = &bpf_prog as *const sock_fprog; - { - let rc = libc::prctl( - libc::PR_SET_SECCOMP, - libc::SECCOMP_MODE_FILTER, - bpf_prog_ptr, - ); - if rc != 0 { - return Err(InstallationError::Prctl(*libc::__errno_location())); - } - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - #![allow(clippy::undocumented_unsafe_blocks)] - - use std::collections::HashMap; - use std::sync::Arc; - use std::thread; - use super::*; - use crate::common::BpfProgram; - - #[test] - fn test_deserialize_binary() { - // Malformed bincode binary. - { - let data = "adassafvc".to_string(); - deserialize_binary(data.as_bytes(), None).unwrap_err(); + // SAFETY: Safe as all args are correct. + unsafe { + let r = seccomp_arch_add(bpf_filter, arch.to_scmp_type()); + if r != 0 && r != MINUS_EEXIST { + return Err(CompilationError::LibSeccompArch); + } } - // Test that the binary deserialization is correct, and that the thread keys - // have been lowercased. - { - let bpf_prog = vec![ - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 0, - }, - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 4, - }, - ]; - let mut filter_map: HashMap = HashMap::new(); - filter_map.insert("VcpU".to_string(), bpf_prog.clone()); - let bytes = bincode::serialize(&filter_map).unwrap(); - - let mut expected_res = BpfThreadMap::new(); - expected_res.insert("vcpu".to_string(), Arc::new(bpf_prog)); - assert_eq!(deserialize_binary(&bytes[..], None).unwrap(), expected_res); + for rule in filter.filter.iter() { + // SAFETY: Safe as all args are correct. + let syscall = unsafe { + let r = seccomp_syscall_resolve_name(rule.syscall.as_ptr()); + if r == __NR_SCMP_ERROR { + return Err(CompilationError::LibSeccompSycall); + } + r + }; + + // TODO remove when we drop deprecated "basic" arg from cli. + // "basic" bpf means it ignores condition checks. + if basic { + // SAFETY: Safe as all args are correct. + unsafe { + if seccomp_rule_add(bpf_filter, filter_action, syscall, 0) != 0 { + return Err(CompilationError::LibSeccompRule); + } + } + } else if let Some(rules) = &rule.args { + let comparators = rules + .iter() + .map(|rule| rule.to_scmp_type()) + .collect::>(); + + // SAFETY: Safe as all args are correct. + // We can assume no one will define u32::MAX + // filters for a syscall. + #[allow(clippy::cast_possible_truncation)] + unsafe { + if seccomp_rule_add_array( + bpf_filter, + filter_action, + syscall, + comparators.len() as u32, + comparators.as_ptr(), + ) != 0 + { + return Err(CompilationError::LibSeccompRule); + } + } + } else { + // SAFETY: Safe as all args are correct. + unsafe { + if seccomp_rule_add(bpf_filter, filter_action, syscall, 0) != 0 { + return Err(CompilationError::LibSeccompRule); + } + } + } } - // Test deserialization with binary_limit. - { - let bpf_prog = vec![sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 0, - }]; - - let mut filter_map: HashMap = HashMap::new(); - filter_map.insert("t1".to_string(), bpf_prog.clone()); - - let bytes = bincode::serialize(&filter_map).unwrap(); - - // Binary limit too low. - assert!(matches!( - deserialize_binary(&bytes[..], Some(20)).unwrap_err(), - DeserializationError::Bincode(error) - if error.to_string() == "the size limit has been reached" - )); - - let mut expected_res = BpfThreadMap::new(); - expected_res.insert("t1".to_string(), Arc::new(bpf_prog)); - - // Correct binary limit. - assert_eq!( - deserialize_binary(&bytes[..], Some(50)).unwrap(), - expected_res - ); + // SAFETY: Safe as all args are correect. + unsafe { + if seccomp_export_bpf(bpf_filter, memfd.as_raw_fd()) != 0 { + return Err(CompilationError::LibSeccompExport); + } } + memfd.rewind().map_err(CompilationError::MemfdRewind)?; + + // Cast is safe because usize == u64 + #[allow(clippy::cast_possible_truncation)] + let size = memfd.metadata().unwrap().size() as usize; + // Bpf instructions are 8 byte values and 4 byte alignment. + // We use u64 to satisfy these requirements. + let instructions = size / std::mem::size_of::(); + let mut bpf = vec![0_u64; instructions]; + + memfd + .read_exact(bpf.as_mut_bytes()) + .map_err(CompilationError::MemfdRead)?; + memfd.rewind().map_err(CompilationError::MemfdRewind)?; + + bpf_map.insert(name.clone(), bpf); } - #[test] - fn test_filter_apply() { - // Test filter too large. - thread::spawn(|| { - let filter: BpfProgram = vec![ - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 0, - }; - 5000 // Limit is 4096 - ]; - - // Apply seccomp filter. - assert_eq!( - apply_filter(&filter).unwrap_err(), - InstallationError::FilterTooLarge - ); - }) - .join() - .unwrap(); + let output_file = File::create(out_path).map_err(CompilationError::OutputCreate)?; - // Test empty filter. - thread::spawn(|| { - let filter: BpfProgram = vec![]; - - assert_eq!(filter.len(), 0); - - let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; - assert_eq!(seccomp_level, 0); - - apply_filter(&filter).unwrap(); - - // test that seccomp level remains 0 on failure. - let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; - assert_eq!(seccomp_level, 0); - }) - .join() - .unwrap(); - - // Test invalid BPF code. - thread::spawn(|| { - let filter = vec![sock_filter { - // invalid opcode - code: 9999, - jt: 0, - jf: 0, - k: 0, - }]; - - let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; - assert_eq!(seccomp_level, 0); - - assert_eq!( - apply_filter(&filter).unwrap_err(), - InstallationError::Prctl(22) - ); - - // test that seccomp level remains 0 on failure. - let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; - assert_eq!(seccomp_level, 0); - }) - .join() - .unwrap(); - } + bincode::serialize_into(output_file, &bpf_map).map_err(CompilationError::BincodeSerialize)?; + Ok(()) } diff --git a/src/seccompiler/src/seccompiler_bin.rs b/src/seccompiler/src/seccompiler_bin.rs deleted file mode 100644 index 890a2a3ecdb..00000000000 --- a/src/seccompiler/src/seccompiler_bin.rs +++ /dev/null @@ -1,578 +0,0 @@ -// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -//! seccompiler-bin is a program that compiles multi-threaded seccomp-bpf filters expressed as JSON -//! into raw BPF programs, serializing them and outputting them to a file. -//! -//! Used in conjunction with the provided library crate, one can deserialize the binary filters -//! and easily install them on a per-thread basis, in order to achieve a quick and robust -//! seccomp-based jailing solution. -//! -//! See the documentation on github for more information. -//! -//! ```text -//! The compilation goes through a couple of steps, from JSON to BPF: -//! -//! JSON -//! | -//! (via serde_json) -//! | -//! V -//! collection of `Filter` objects -//! | -//! (via Compiler.compile_blob(...)) -//! | -//! V -//! collection of `SeccompFilter` objects -//! (IR - intermediate representation) -//! | -//! (via SeccompFilter.try_into::(...)) -//! | -//! V -//! collection of `BpfProgram` objects -//! ``` - -use std::collections::BTreeMap; -use std::convert::TryInto; -use std::fs::File; -use std::io::BufReader; -use std::path::PathBuf; - -mod backend; -mod common; -mod compiler; -mod syscall_table; - -use backend::{TargetArch, TargetArchError}; -use bincode::Error as BincodeError; -use common::BpfProgram; -use compiler::{CompilationError, Compiler, JsonFile}; -use serde_json::error::Error as JSONError; -use utils::arg_parser::{ - ArgParser, Argument, Arguments as ArgumentsBag, UtilsArgParserError as ArgParserError, -}; - -const SECCOMPILER_VERSION: &str = env!("CARGO_PKG_VERSION"); -const DEFAULT_OUTPUT_FILENAME: &str = "seccomp_binary_filter.out"; - -#[derive(Debug, thiserror::Error)] -enum SeccompError { - #[error("Bincode (de)serialization failed: {0}")] - Bincode(BincodeError), - #[error("{0}")] - Compilation(CompilationError), - #[error("{}", format!("Failed to open file {:?}: {1}", .0, .1).replace('\"', ""))] - FileOpen(PathBuf, std::io::Error), - #[error("Error parsing JSON: {0}")] - Json(JSONError), - #[error("Missing input file.")] - MissingInputFile, - #[error("Missing target arch.")] - MissingTargetArch, - #[error("{0}")] - Arch(#[from] TargetArchError), -} - -#[derive(Debug, PartialEq)] -struct Arguments { - input_file: String, - output_file: String, - target_arch: TargetArch, - is_basic: bool, -} - -fn build_arg_parser() -> ArgParser<'static> { - ArgParser::new() - .arg( - Argument::new("input-file") - .required(true) - .takes_value(true) - .help("File path of the JSON input."), - ) - .arg( - Argument::new("output-file") - .required(false) - .takes_value(true) - .default_value(DEFAULT_OUTPUT_FILENAME) - .help("Optional path of the output file."), - ) - .arg( - Argument::new("target-arch") - .required(true) - .takes_value(true) - .help( - "The computer architecture where the BPF program runs. Supported \ - architectures: x86_64, aarch64.", - ), - ) - .arg(Argument::new("basic").takes_value(false).help( - "Deprecated! Transforms the filters into basic filters. Drops all argument checks and \ - rule-level actions. Not recommended.", - )) -} - -fn get_argument_values(arguments: &ArgumentsBag) -> Result { - let Some(arch_string) = arguments.single_value("target-arch") else { - return Err(SeccompError::MissingTargetArch); - }; - let target_arch: TargetArch = arch_string.as_str().try_into()?; - - let Some(input_file) = arguments.single_value("input-file") else { - return Err(SeccompError::MissingInputFile); - }; - - let is_basic = arguments.flag_present("basic"); - if is_basic { - println!( - "Warning! You are using a deprecated parameter: --basic, that will be removed in a \ - future version.\n" - ); - } - - Ok(Arguments { - target_arch, - input_file: input_file.to_owned(), - // Safe to unwrap because it has a default value - output_file: arguments.single_value("output-file").unwrap().to_owned(), - is_basic, - }) -} - -fn compile(args: &Arguments) -> Result<(), SeccompError> { - let input_file = File::open(&args.input_file) - .map_err(|err| SeccompError::FileOpen(PathBuf::from(&args.input_file), err))?; - let mut input_reader = BufReader::new(input_file); - let filters = - serde_json::from_reader::<_, JsonFile>(&mut input_reader).map_err(SeccompError::Json)?; - let compiler = Compiler::new(args.target_arch); - - // transform the IR into a Map of BPFPrograms - let bpf_data: BTreeMap = compiler - .compile_blob(filters.0, args.is_basic) - .map_err(SeccompError::Compilation)?; - - // serialize the BPF programs & output them to a file - let output_file = File::create(&args.output_file) - .map_err(|err| SeccompError::FileOpen(PathBuf::from(&args.output_file), err))?; - bincode::serialize_into(output_file, &bpf_data).map_err(SeccompError::Bincode)?; - - Ok(()) -} - -#[derive(Debug, thiserror::Error, displaydoc::Display)] -enum SeccompilerError { - /// Argument Parsing Error: {0} - ArgParsing(ArgParserError), - /// {0} \n\nFor more information try --help. - InvalidArgumentValue(SeccompError), - /// {0} - Error(SeccompError), -} - -fn main() -> core::result::Result<(), SeccompilerError> { - let result = main_exec(); - if let Err(e) = result { - eprintln!("{}", e); - Err(e) - } else { - Ok(()) - } -} - -fn main_exec() -> core::result::Result<(), SeccompilerError> { - let mut arg_parser = build_arg_parser(); - - arg_parser - .parse_from_cmdline() - .map_err(SeccompilerError::ArgParsing)?; - - if arg_parser.arguments().flag_present("help") { - println!("Seccompiler-bin v{}\n", SECCOMPILER_VERSION); - println!("{}", arg_parser.formatted_help()); - return Ok(()); - } - if arg_parser.arguments().flag_present("version") { - println!("Seccompiler-bin v{}\n", SECCOMPILER_VERSION); - return Ok(()); - } - - let args = get_argument_values(arg_parser.arguments()) - .map_err(SeccompilerError::InvalidArgumentValue)?; - - compile(&args).map_err(SeccompilerError::Error)?; - - println!("Filter successfully compiled into: {}", args.output_file); - Ok(()) -} - -#[cfg(test)] -mod tests { - #![allow(clippy::undocumented_unsafe_blocks)] - - use std::io; - use std::io::Write; - use std::path::PathBuf; - - use bincode::Error as BincodeError; - use vmm_sys_util::tempfile::TempFile; - - use super::compiler::CompilationError as FilterFormatError; - use super::{ - build_arg_parser, compile, get_argument_values, Arguments, SeccompError, - DEFAULT_OUTPUT_FILENAME, - }; - use crate::backend::{TargetArch, TargetArchError}; - - // Correct JSON input data - static CORRECT_JSON_INPUT: &str = r#" - { - "thread_1": { - "default_action": { - "errno": 12 - }, - "filter_action": "allow", - "filter": [ - { - "syscall": "open" - }, - { - "syscall": "close" - }, - { - "syscall": "stat" - }, - { - "syscall": "futex", - "args": [ - { - "index": 2, - "type": "dword", - "op": "le", - "val": 65 - }, - { - "index": 1, - "type": "qword", - "op": "ne", - "val": 80 - } - ] - }, - { - "syscall": "futex", - "args": [ - { - "index": 3, - "type": "qword", - "op": "gt", - "val": 65 - }, - { - "index": 1, - "type": "qword", - "op": "lt", - "val": 80 - } - ] - }, - { - "syscall": "futex", - "args": [ - { - "index": 3, - "type": "qword", - "op": "ge", - "val": 65 - } - ] - }, - { - "syscall": "ioctl", - "args": [ - { - "index": 3, - "type": "dword", - "op": { - "masked_eq": 100 - }, - "val": 65 - } - ] - } - ] - }, - "thread_2": { - "default_action": "trap", - "filter_action": "allow", - "filter": [ - { - "syscall": "ioctl", - "args": [ - { - "index": 3, - "type": "dword", - "op": "eq", - "val": 65 - } - ] - } - ] - } - } - "#; - - #[test] - fn test_error_messages() { - let path = PathBuf::from("/path"); - assert_eq!( - format!( - "{}", - SeccompError::Bincode(BincodeError::new(bincode::ErrorKind::SizeLimit)) - ), - format!( - "Bincode (de)serialization failed: {}", - BincodeError::new(bincode::ErrorKind::SizeLimit) - ) - ); - assert_eq!( - format!( - "{}", - SeccompError::Compilation(FilterFormatError::SyscallName( - "dsaa".to_string(), - TargetArch::aarch64 - )) - ), - format!( - "{}", - FilterFormatError::SyscallName("dsaa".to_string(), TargetArch::aarch64) - ) - ); - assert_eq!( - format!( - "{}", - SeccompError::FileOpen(path.clone(), io::Error::from_raw_os_error(2)) - ), - format!( - "Failed to open file {:?}: {}", - path, - io::Error::from_raw_os_error(2) - ) - .replace('\"', "") - ); - assert_eq!( - format!( - "{}", - SeccompError::Json(serde_json::from_str::("").unwrap_err()) - ), - format!( - "Error parsing JSON: {}", - serde_json::from_str::("").unwrap_err() - ) - ); - assert_eq!( - format!("{}", SeccompError::MissingInputFile), - "Missing input file." - ); - assert_eq!( - format!("{}", SeccompError::MissingTargetArch), - "Missing target arch." - ); - assert_eq!( - format!( - "{}", - SeccompError::Arch(TargetArchError::InvalidString("lala".to_string())) - ), - format!("{}", TargetArchError::InvalidString("lala".to_string())) - ); - } - - #[test] - fn test_get_argument_values() { - let arg_parser = build_arg_parser(); - // correct arguments - let arguments = &mut arg_parser.arguments().clone(); - arguments - .parse( - vec![ - "seccompiler-bin", - "--input-file", - "foo.txt", - "--target-arch", - "x86_64", - ] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .unwrap(); - assert_eq!( - get_argument_values(arguments).unwrap(), - Arguments { - input_file: "foo.txt".to_string(), - output_file: DEFAULT_OUTPUT_FILENAME.to_string(), - target_arch: TargetArch::x86_64, - is_basic: false, - } - ); - - let arguments = &mut arg_parser.arguments().clone(); - arguments - .parse( - vec![ - "seccompiler-bin", - "--input-file", - "foo.txt", - "--target-arch", - "x86_64", - "--output-file", - "/path.to/file.txt", - "--basic", - ] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .unwrap(); - assert_eq!( - get_argument_values(arguments).unwrap(), - Arguments { - input_file: "foo.txt".to_string(), - output_file: "/path.to/file.txt".to_string(), - target_arch: TargetArch::x86_64, - is_basic: true - } - ); - - // no args - let arguments = &mut arg_parser.arguments().clone(); - assert!(arguments - .parse( - vec!["seccompiler-bin"] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .is_err()); - - // missing --target-arch - let arguments = &mut arg_parser.arguments().clone(); - assert!(arguments - .parse( - vec!["seccompiler-bin", "--input-file", "foo.txt"] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .is_err()); - - // missing --input-file - let arguments = &mut arg_parser.arguments().clone(); - assert!(arguments - .parse( - vec!["seccompiler-bin", "--target-arch", "x86_64"] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .is_err()); - - // invalid --target-arch - let arguments = &mut arg_parser.arguments().clone(); - arguments - .parse( - vec![ - "seccompiler-bin", - "--input-file", - "foo.txt", - "--target-arch", - "x86_64das", - "--output-file", - "/path.to/file.txt", - ] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .unwrap(); - get_argument_values(arguments).unwrap_err(); - - // invalid value supplied to --basic - let arguments = &mut arg_parser.arguments().clone(); - assert!(arguments - .parse( - vec![ - "seccompiler-bin", - "--input-file", - "foo.txt", - "--target-arch", - "x86_64", - "--basic", - "invalid", - ] - .into_iter() - .map(String::from) - .collect::>() - .as_ref(), - ) - .is_err()); - } - - #[allow(clippy::useless_asref)] - #[test] - fn test_compile() { - // --input-file was deleted - { - let mut in_file = TempFile::new().unwrap(); - in_file.remove().unwrap(); - let args = Arguments { - input_file: in_file.as_path().to_str().unwrap().to_string(), - target_arch: TargetArch::x86_64, - output_file: "bpf.out".to_string(), - is_basic: false, - }; - - match compile(&args).unwrap_err() { - SeccompError::FileOpen(buf, _) => assert_eq!(buf, PathBuf::from(in_file.as_path())), - _ => panic!("Expected FileOpen error."), - } - } - - // test a successful compilation - { - let in_file = TempFile::new().unwrap(); - let out_file = TempFile::new().unwrap(); - - in_file - .as_file() - .write_all(CORRECT_JSON_INPUT.as_bytes()) - .unwrap(); - - let arguments = Arguments { - input_file: in_file.as_path().to_str().unwrap().to_string(), - output_file: out_file.as_path().to_str().unwrap().to_string(), - target_arch: TargetArch::x86_64, - is_basic: false, - }; - - // do the compilation & check for errors - compile(&arguments).unwrap(); - - // also check with is_basic: true - let arguments = Arguments { - input_file: in_file.as_path().to_str().unwrap().to_string(), - output_file: out_file.as_path().to_str().unwrap().to_string(), - target_arch: TargetArch::x86_64, - is_basic: true, - }; - - // do the compilation & check for errors - compile(&arguments).unwrap(); - } - } -} diff --git a/src/seccompiler/src/syscall_table/aarch64.rs b/src/seccompiler/src/syscall_table/aarch64.rs deleted file mode 100644 index 386d09b78d3..00000000000 --- a/src/seccompiler/src/syscall_table/aarch64.rs +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -// This file is auto-generated by `tools/devtool generate_syscall_tables`. -// Do NOT manually edit! -// Generated at: Mon 15 Nov 11:41:50 UTC 2021 -// Kernel version: 5.10 - -use std::collections::HashMap; - -pub fn make_syscall_table(map: &mut HashMap) { - map.insert("accept4".to_string(), 242); - map.insert("accept".to_string(), 202); - map.insert("acct".to_string(), 89); - map.insert("add_key".to_string(), 217); - map.insert("adjtimex".to_string(), 171); - map.insert("bind".to_string(), 200); - map.insert("bpf".to_string(), 280); - map.insert("brk".to_string(), 214); - map.insert("capget".to_string(), 90); - map.insert("capset".to_string(), 91); - map.insert("chdir".to_string(), 49); - map.insert("chroot".to_string(), 51); - map.insert("clock_adjtime".to_string(), 266); - map.insert("clock_getres".to_string(), 114); - map.insert("clock_gettime".to_string(), 113); - map.insert("clock_nanosleep".to_string(), 115); - map.insert("clock_settime".to_string(), 112); - map.insert("clone3".to_string(), 435); - map.insert("clone".to_string(), 220); - map.insert("close_range".to_string(), 436); - map.insert("close".to_string(), 57); - map.insert("connect".to_string(), 203); - map.insert("copy_file_range".to_string(), 285); - map.insert("delete_module".to_string(), 106); - map.insert("dup3".to_string(), 24); - map.insert("dup".to_string(), 23); - map.insert("epoll_create1".to_string(), 20); - map.insert("epoll_ctl".to_string(), 21); - map.insert("epoll_pwait".to_string(), 22); - map.insert("eventfd2".to_string(), 19); - map.insert("execveat".to_string(), 281); - map.insert("execve".to_string(), 221); - map.insert("exit_group".to_string(), 94); - map.insert("exit".to_string(), 93); - map.insert("faccessat2".to_string(), 439); - map.insert("faccessat".to_string(), 48); - map.insert("fadvise64".to_string(), 223); - map.insert("fallocate".to_string(), 47); - map.insert("fanotify_init".to_string(), 262); - map.insert("fanotify_mark".to_string(), 263); - map.insert("fchdir".to_string(), 50); - map.insert("fchmodat".to_string(), 53); - map.insert("fchmod".to_string(), 52); - map.insert("fchownat".to_string(), 54); - map.insert("fchown".to_string(), 55); - map.insert("fcntl".to_string(), 25); - map.insert("fdatasync".to_string(), 83); - map.insert("fgetxattr".to_string(), 10); - map.insert("finit_module".to_string(), 273); - map.insert("flistxattr".to_string(), 13); - map.insert("flock".to_string(), 32); - map.insert("fremovexattr".to_string(), 16); - map.insert("fsconfig".to_string(), 431); - map.insert("fsetxattr".to_string(), 7); - map.insert("fsmount".to_string(), 432); - map.insert("fsopen".to_string(), 430); - map.insert("fspick".to_string(), 433); - map.insert("fstatfs".to_string(), 44); - map.insert("fstat".to_string(), 80); - map.insert("fsync".to_string(), 82); - map.insert("ftruncate".to_string(), 46); - map.insert("futex".to_string(), 98); - map.insert("getcpu".to_string(), 168); - map.insert("getcwd".to_string(), 17); - map.insert("getdents64".to_string(), 61); - map.insert("getegid".to_string(), 177); - map.insert("geteuid".to_string(), 175); - map.insert("getgid".to_string(), 176); - map.insert("getgroups".to_string(), 158); - map.insert("getitimer".to_string(), 102); - map.insert("get_mempolicy".to_string(), 236); - map.insert("getpeername".to_string(), 205); - map.insert("getpgid".to_string(), 155); - map.insert("getpid".to_string(), 172); - map.insert("getppid".to_string(), 173); - map.insert("getpriority".to_string(), 141); - map.insert("getrandom".to_string(), 278); - map.insert("getresgid".to_string(), 150); - map.insert("getresuid".to_string(), 148); - map.insert("getrlimit".to_string(), 163); - map.insert("get_robust_list".to_string(), 100); - map.insert("getrusage".to_string(), 165); - map.insert("getsid".to_string(), 156); - map.insert("getsockname".to_string(), 204); - map.insert("getsockopt".to_string(), 209); - map.insert("gettid".to_string(), 178); - map.insert("gettimeofday".to_string(), 169); - map.insert("getuid".to_string(), 174); - map.insert("getxattr".to_string(), 8); - map.insert("init_module".to_string(), 105); - map.insert("inotify_add_watch".to_string(), 27); - map.insert("inotify_init1".to_string(), 26); - map.insert("inotify_rm_watch".to_string(), 28); - map.insert("io_cancel".to_string(), 3); - map.insert("ioctl".to_string(), 29); - map.insert("io_destroy".to_string(), 1); - map.insert("io_getevents".to_string(), 4); - map.insert("io_pgetevents".to_string(), 292); - map.insert("ioprio_get".to_string(), 31); - map.insert("ioprio_set".to_string(), 30); - map.insert("io_setup".to_string(), 0); - map.insert("io_submit".to_string(), 2); - map.insert("io_uring_enter".to_string(), 426); - map.insert("io_uring_register".to_string(), 427); - map.insert("io_uring_setup".to_string(), 425); - map.insert("kcmp".to_string(), 272); - map.insert("kexec_file_load".to_string(), 294); - map.insert("kexec_load".to_string(), 104); - map.insert("keyctl".to_string(), 219); - map.insert("kill".to_string(), 129); - map.insert("lgetxattr".to_string(), 9); - map.insert("linkat".to_string(), 37); - map.insert("listen".to_string(), 201); - map.insert("listxattr".to_string(), 11); - map.insert("llistxattr".to_string(), 12); - map.insert("lookup_dcookie".to_string(), 18); - map.insert("lremovexattr".to_string(), 15); - map.insert("lseek".to_string(), 62); - map.insert("lsetxattr".to_string(), 6); - map.insert("madvise".to_string(), 233); - map.insert("mbind".to_string(), 235); - map.insert("membarrier".to_string(), 283); - map.insert("memfd_create".to_string(), 279); - map.insert("migrate_pages".to_string(), 238); - map.insert("mincore".to_string(), 232); - map.insert("mkdirat".to_string(), 34); - map.insert("mknodat".to_string(), 33); - map.insert("mlock2".to_string(), 284); - map.insert("mlockall".to_string(), 230); - map.insert("mlock".to_string(), 228); - map.insert("mmap".to_string(), 222); - map.insert("mount".to_string(), 40); - map.insert("move_mount".to_string(), 429); - map.insert("move_pages".to_string(), 239); - map.insert("mprotect".to_string(), 226); - map.insert("mq_getsetattr".to_string(), 185); - map.insert("mq_notify".to_string(), 184); - map.insert("mq_open".to_string(), 180); - map.insert("mq_timedreceive".to_string(), 183); - map.insert("mq_timedsend".to_string(), 182); - map.insert("mq_unlink".to_string(), 181); - map.insert("mremap".to_string(), 216); - map.insert("msgctl".to_string(), 187); - map.insert("msgget".to_string(), 186); - map.insert("msgrcv".to_string(), 188); - map.insert("msgsnd".to_string(), 189); - map.insert("msync".to_string(), 227); - map.insert("munlockall".to_string(), 231); - map.insert("munlock".to_string(), 229); - map.insert("munmap".to_string(), 215); - map.insert("name_to_handle_at".to_string(), 264); - map.insert("nanosleep".to_string(), 101); - map.insert("newfstatat".to_string(), 79); - map.insert("nfsservctl".to_string(), 42); - map.insert("openat2".to_string(), 437); - map.insert("openat".to_string(), 56); - map.insert("open_by_handle_at".to_string(), 265); - map.insert("open_tree".to_string(), 428); - map.insert("perf_event_open".to_string(), 241); - map.insert("personality".to_string(), 92); - map.insert("pidfd_getfd".to_string(), 438); - map.insert("pidfd_open".to_string(), 434); - map.insert("pidfd_send_signal".to_string(), 424); - map.insert("pipe2".to_string(), 59); - map.insert("pivot_root".to_string(), 41); - map.insert("pkey_alloc".to_string(), 289); - map.insert("pkey_free".to_string(), 290); - map.insert("pkey_mprotect".to_string(), 288); - map.insert("ppoll".to_string(), 73); - map.insert("prctl".to_string(), 167); - map.insert("pread64".to_string(), 67); - map.insert("preadv2".to_string(), 286); - map.insert("preadv".to_string(), 69); - map.insert("prlimit64".to_string(), 261); - map.insert("process_madvise".to_string(), 440); - map.insert("process_vm_readv".to_string(), 270); - map.insert("process_vm_writev".to_string(), 271); - map.insert("pselect6".to_string(), 72); - map.insert("ptrace".to_string(), 117); - map.insert("pwrite64".to_string(), 68); - map.insert("pwritev2".to_string(), 287); - map.insert("pwritev".to_string(), 70); - map.insert("quotactl".to_string(), 60); - map.insert("readahead".to_string(), 213); - map.insert("readlinkat".to_string(), 78); - map.insert("read".to_string(), 63); - map.insert("readv".to_string(), 65); - map.insert("reboot".to_string(), 142); - map.insert("recvfrom".to_string(), 207); - map.insert("recvmmsg".to_string(), 243); - map.insert("recvmsg".to_string(), 212); - map.insert("remap_file_pages".to_string(), 234); - map.insert("removexattr".to_string(), 14); - map.insert("renameat2".to_string(), 276); - map.insert("renameat".to_string(), 38); - map.insert("request_key".to_string(), 218); - map.insert("restart_syscall".to_string(), 128); - map.insert("rseq".to_string(), 293); - map.insert("rt_sigaction".to_string(), 134); - map.insert("rt_sigpending".to_string(), 136); - map.insert("rt_sigprocmask".to_string(), 135); - map.insert("rt_sigqueueinfo".to_string(), 138); - map.insert("rt_sigreturn".to_string(), 139); - map.insert("rt_sigsuspend".to_string(), 133); - map.insert("rt_sigtimedwait".to_string(), 137); - map.insert("rt_tgsigqueueinfo".to_string(), 240); - map.insert("sched_getaffinity".to_string(), 123); - map.insert("sched_getattr".to_string(), 275); - map.insert("sched_getparam".to_string(), 121); - map.insert("sched_get_priority_max".to_string(), 125); - map.insert("sched_get_priority_min".to_string(), 126); - map.insert("sched_getscheduler".to_string(), 120); - map.insert("sched_rr_get_interval".to_string(), 127); - map.insert("sched_setaffinity".to_string(), 122); - map.insert("sched_setattr".to_string(), 274); - map.insert("sched_setparam".to_string(), 118); - map.insert("sched_setscheduler".to_string(), 119); - map.insert("sched_yield".to_string(), 124); - map.insert("seccomp".to_string(), 277); - map.insert("semctl".to_string(), 191); - map.insert("semget".to_string(), 190); - map.insert("semop".to_string(), 193); - map.insert("semtimedop".to_string(), 192); - map.insert("sendfile".to_string(), 71); - map.insert("sendmmsg".to_string(), 269); - map.insert("sendmsg".to_string(), 211); - map.insert("sendto".to_string(), 206); - map.insert("setdomainname".to_string(), 162); - map.insert("setfsgid".to_string(), 152); - map.insert("setfsuid".to_string(), 151); - map.insert("setgid".to_string(), 144); - map.insert("setgroups".to_string(), 159); - map.insert("sethostname".to_string(), 161); - map.insert("setitimer".to_string(), 103); - map.insert("set_mempolicy".to_string(), 237); - map.insert("setns".to_string(), 268); - map.insert("setpgid".to_string(), 154); - map.insert("setpriority".to_string(), 140); - map.insert("setregid".to_string(), 143); - map.insert("setresgid".to_string(), 149); - map.insert("setresuid".to_string(), 147); - map.insert("setreuid".to_string(), 145); - map.insert("setrlimit".to_string(), 164); - map.insert("set_robust_list".to_string(), 99); - map.insert("setsid".to_string(), 157); - map.insert("setsockopt".to_string(), 208); - map.insert("set_tid_address".to_string(), 96); - map.insert("settimeofday".to_string(), 170); - map.insert("setuid".to_string(), 146); - map.insert("setxattr".to_string(), 5); - map.insert("shmat".to_string(), 196); - map.insert("shmctl".to_string(), 195); - map.insert("shmdt".to_string(), 197); - map.insert("shmget".to_string(), 194); - map.insert("shutdown".to_string(), 210); - map.insert("sigaltstack".to_string(), 132); - map.insert("signalfd4".to_string(), 74); - map.insert("socketpair".to_string(), 199); - map.insert("socket".to_string(), 198); - map.insert("splice".to_string(), 76); - map.insert("statfs".to_string(), 43); - map.insert("statx".to_string(), 291); - map.insert("swapoff".to_string(), 225); - map.insert("swapon".to_string(), 224); - map.insert("symlinkat".to_string(), 36); - map.insert("sync_file_range".to_string(), 84); - map.insert("syncfs".to_string(), 267); - map.insert("sync".to_string(), 81); - map.insert("sysinfo".to_string(), 179); - map.insert("syslog".to_string(), 116); - map.insert("tee".to_string(), 77); - map.insert("tgkill".to_string(), 131); - map.insert("timer_create".to_string(), 107); - map.insert("timer_delete".to_string(), 111); - map.insert("timerfd_create".to_string(), 85); - map.insert("timerfd_gettime".to_string(), 87); - map.insert("timerfd_settime".to_string(), 86); - map.insert("timer_getoverrun".to_string(), 109); - map.insert("timer_gettime".to_string(), 108); - map.insert("timer_settime".to_string(), 110); - map.insert("times".to_string(), 153); - map.insert("tkill".to_string(), 130); - map.insert("truncate".to_string(), 45); - map.insert("umask".to_string(), 166); - map.insert("umount2".to_string(), 39); - map.insert("uname".to_string(), 160); - map.insert("unlinkat".to_string(), 35); - map.insert("unshare".to_string(), 97); - map.insert("userfaultfd".to_string(), 282); - map.insert("utimensat".to_string(), 88); - map.insert("vhangup".to_string(), 58); - map.insert("vmsplice".to_string(), 75); - map.insert("wait4".to_string(), 260); - map.insert("waitid".to_string(), 95); - map.insert("write".to_string(), 64); - map.insert("writev".to_string(), 66); -} diff --git a/src/seccompiler/src/syscall_table/mod.rs b/src/seccompiler/src/syscall_table/mod.rs deleted file mode 100644 index 3dca50c748d..00000000000 --- a/src/seccompiler/src/syscall_table/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -mod aarch64; -mod x86_64; - -use std::collections::HashMap; - -use crate::backend::TargetArch; - -/// Creates and owns a mapping from the arch-specific syscall name to the right number. -#[derive(Debug)] -pub struct SyscallTable { - map: HashMap, - arch: TargetArch, -} - -/// Number of syscalls for x86_64 (rough upper bound). -const MAP_CAPACITY: usize = 351; - -impl SyscallTable { - /// Create new syscall table - pub fn new(arch: TargetArch) -> Self { - let mut instance = Self { - arch, - map: HashMap::with_capacity(MAP_CAPACITY), - }; - - instance.populate_map(); - - instance - } - - /// Returns the arch-specific syscall number based on the given name. - pub fn get_syscall_nr(&self, sys_name: &str) -> Option { - self.map.get(sys_name).copied() - } - - /// Populates the arch-specific syscall map. - fn populate_map(&mut self) { - match self.arch { - TargetArch::aarch64 => aarch64::make_syscall_table(&mut self.map), - TargetArch::x86_64 => x86_64::make_syscall_table(&mut self.map), - } - } -} - -#[cfg(test)] -mod tests { - use super::SyscallTable; - use crate::backend::TargetArch; - - #[test] - fn test_get_syscall_nr() { - // get number for a valid syscall - let instance_x86_64 = SyscallTable::new(TargetArch::x86_64); - let instance_aarch64 = SyscallTable::new(TargetArch::aarch64); - - assert_eq!(instance_x86_64.get_syscall_nr("close").unwrap(), 3); - assert_eq!(instance_aarch64.get_syscall_nr("close").unwrap(), 57); - - // invalid syscall name - assert!(instance_x86_64.get_syscall_nr("nosyscall").is_none()); - assert!(instance_aarch64.get_syscall_nr("nosyscall").is_none()); - } -} diff --git a/src/seccompiler/src/syscall_table/x86_64.rs b/src/seccompiler/src/syscall_table/x86_64.rs deleted file mode 100644 index 9350bd5ce57..00000000000 --- a/src/seccompiler/src/syscall_table/x86_64.rs +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -// This file is auto-generated by `tools/devtool generate_syscall_tables`. -// Do NOT manually edit! -// Generated at: Mon 15 Nov 11:41:50 UTC 2021 -// Kernel version: 5.10 - -use std::collections::HashMap; - -pub fn make_syscall_table(map: &mut HashMap) { - map.insert("accept4".to_string(), 288); - map.insert("accept".to_string(), 43); - map.insert("access".to_string(), 21); - map.insert("acct".to_string(), 163); - map.insert("add_key".to_string(), 248); - map.insert("adjtimex".to_string(), 159); - map.insert("afs_syscall".to_string(), 183); - map.insert("alarm".to_string(), 37); - map.insert("arch_prctl".to_string(), 158); - map.insert("bind".to_string(), 49); - map.insert("bpf".to_string(), 321); - map.insert("brk".to_string(), 12); - map.insert("capget".to_string(), 125); - map.insert("capset".to_string(), 126); - map.insert("chdir".to_string(), 80); - map.insert("chmod".to_string(), 90); - map.insert("chown".to_string(), 92); - map.insert("chroot".to_string(), 161); - map.insert("clock_adjtime".to_string(), 305); - map.insert("clock_getres".to_string(), 229); - map.insert("clock_gettime".to_string(), 228); - map.insert("clock_nanosleep".to_string(), 230); - map.insert("clock_settime".to_string(), 227); - map.insert("clone3".to_string(), 435); - map.insert("clone".to_string(), 56); - map.insert("close_range".to_string(), 436); - map.insert("close".to_string(), 3); - map.insert("connect".to_string(), 42); - map.insert("copy_file_range".to_string(), 326); - map.insert("create_module".to_string(), 174); - map.insert("creat".to_string(), 85); - map.insert("delete_module".to_string(), 176); - map.insert("dup2".to_string(), 33); - map.insert("dup3".to_string(), 292); - map.insert("dup".to_string(), 32); - map.insert("epoll_create1".to_string(), 291); - map.insert("epoll_create".to_string(), 213); - map.insert("epoll_ctl_old".to_string(), 214); - map.insert("epoll_ctl".to_string(), 233); - map.insert("epoll_pwait".to_string(), 281); - map.insert("epoll_wait_old".to_string(), 215); - map.insert("epoll_wait".to_string(), 232); - map.insert("eventfd2".to_string(), 290); - map.insert("eventfd".to_string(), 284); - map.insert("execveat".to_string(), 322); - map.insert("execve".to_string(), 59); - map.insert("exit_group".to_string(), 231); - map.insert("exit".to_string(), 60); - map.insert("faccessat2".to_string(), 439); - map.insert("faccessat".to_string(), 269); - map.insert("fadvise64".to_string(), 221); - map.insert("fallocate".to_string(), 285); - map.insert("fanotify_init".to_string(), 300); - map.insert("fanotify_mark".to_string(), 301); - map.insert("fchdir".to_string(), 81); - map.insert("fchmodat".to_string(), 268); - map.insert("fchmod".to_string(), 91); - map.insert("fchownat".to_string(), 260); - map.insert("fchown".to_string(), 93); - map.insert("fcntl".to_string(), 72); - map.insert("fdatasync".to_string(), 75); - map.insert("fgetxattr".to_string(), 193); - map.insert("finit_module".to_string(), 313); - map.insert("flistxattr".to_string(), 196); - map.insert("flock".to_string(), 73); - map.insert("fork".to_string(), 57); - map.insert("fremovexattr".to_string(), 199); - map.insert("fsconfig".to_string(), 431); - map.insert("fsetxattr".to_string(), 190); - map.insert("fsmount".to_string(), 432); - map.insert("fsopen".to_string(), 430); - map.insert("fspick".to_string(), 433); - map.insert("fstatfs".to_string(), 138); - map.insert("fstat".to_string(), 5); - map.insert("fsync".to_string(), 74); - map.insert("ftruncate".to_string(), 77); - map.insert("futex".to_string(), 202); - map.insert("futimesat".to_string(), 261); - map.insert("getcpu".to_string(), 309); - map.insert("getcwd".to_string(), 79); - map.insert("getdents64".to_string(), 217); - map.insert("getdents".to_string(), 78); - map.insert("getegid".to_string(), 108); - map.insert("geteuid".to_string(), 107); - map.insert("getgid".to_string(), 104); - map.insert("getgroups".to_string(), 115); - map.insert("getitimer".to_string(), 36); - map.insert("get_kernel_syms".to_string(), 177); - map.insert("get_mempolicy".to_string(), 239); - map.insert("getpeername".to_string(), 52); - map.insert("getpgid".to_string(), 121); - map.insert("getpgrp".to_string(), 111); - map.insert("getpid".to_string(), 39); - map.insert("getpmsg".to_string(), 181); - map.insert("getppid".to_string(), 110); - map.insert("getpriority".to_string(), 140); - map.insert("getrandom".to_string(), 318); - map.insert("getresgid".to_string(), 120); - map.insert("getresuid".to_string(), 118); - map.insert("getrlimit".to_string(), 97); - map.insert("get_robust_list".to_string(), 274); - map.insert("getrusage".to_string(), 98); - map.insert("getsid".to_string(), 124); - map.insert("getsockname".to_string(), 51); - map.insert("getsockopt".to_string(), 55); - map.insert("get_thread_area".to_string(), 211); - map.insert("gettid".to_string(), 186); - map.insert("gettimeofday".to_string(), 96); - map.insert("getuid".to_string(), 102); - map.insert("getxattr".to_string(), 191); - map.insert("init_module".to_string(), 175); - map.insert("inotify_add_watch".to_string(), 254); - map.insert("inotify_init1".to_string(), 294); - map.insert("inotify_init".to_string(), 253); - map.insert("inotify_rm_watch".to_string(), 255); - map.insert("io_cancel".to_string(), 210); - map.insert("ioctl".to_string(), 16); - map.insert("io_destroy".to_string(), 207); - map.insert("io_getevents".to_string(), 208); - map.insert("ioperm".to_string(), 173); - map.insert("io_pgetevents".to_string(), 333); - map.insert("iopl".to_string(), 172); - map.insert("ioprio_get".to_string(), 252); - map.insert("ioprio_set".to_string(), 251); - map.insert("io_setup".to_string(), 206); - map.insert("io_submit".to_string(), 209); - map.insert("io_uring_enter".to_string(), 426); - map.insert("io_uring_register".to_string(), 427); - map.insert("io_uring_setup".to_string(), 425); - map.insert("kcmp".to_string(), 312); - map.insert("kexec_file_load".to_string(), 320); - map.insert("kexec_load".to_string(), 246); - map.insert("keyctl".to_string(), 250); - map.insert("kill".to_string(), 62); - map.insert("lchown".to_string(), 94); - map.insert("lgetxattr".to_string(), 192); - map.insert("linkat".to_string(), 265); - map.insert("link".to_string(), 86); - map.insert("listen".to_string(), 50); - map.insert("listxattr".to_string(), 194); - map.insert("llistxattr".to_string(), 195); - map.insert("lookup_dcookie".to_string(), 212); - map.insert("lremovexattr".to_string(), 198); - map.insert("lseek".to_string(), 8); - map.insert("lsetxattr".to_string(), 189); - map.insert("lstat".to_string(), 6); - map.insert("madvise".to_string(), 28); - map.insert("mbind".to_string(), 237); - map.insert("membarrier".to_string(), 324); - map.insert("memfd_create".to_string(), 319); - map.insert("migrate_pages".to_string(), 256); - map.insert("mincore".to_string(), 27); - map.insert("mkdirat".to_string(), 258); - map.insert("mkdir".to_string(), 83); - map.insert("mknodat".to_string(), 259); - map.insert("mknod".to_string(), 133); - map.insert("mlock2".to_string(), 325); - map.insert("mlockall".to_string(), 151); - map.insert("mlock".to_string(), 149); - map.insert("mmap".to_string(), 9); - map.insert("modify_ldt".to_string(), 154); - map.insert("mount".to_string(), 165); - map.insert("move_mount".to_string(), 429); - map.insert("move_pages".to_string(), 279); - map.insert("mprotect".to_string(), 10); - map.insert("mq_getsetattr".to_string(), 245); - map.insert("mq_notify".to_string(), 244); - map.insert("mq_open".to_string(), 240); - map.insert("mq_timedreceive".to_string(), 243); - map.insert("mq_timedsend".to_string(), 242); - map.insert("mq_unlink".to_string(), 241); - map.insert("mremap".to_string(), 25); - map.insert("msgctl".to_string(), 71); - map.insert("msgget".to_string(), 68); - map.insert("msgrcv".to_string(), 70); - map.insert("msgsnd".to_string(), 69); - map.insert("msync".to_string(), 26); - map.insert("munlockall".to_string(), 152); - map.insert("munlock".to_string(), 150); - map.insert("munmap".to_string(), 11); - map.insert("name_to_handle_at".to_string(), 303); - map.insert("nanosleep".to_string(), 35); - map.insert("newfstatat".to_string(), 262); - map.insert("nfsservctl".to_string(), 180); - map.insert("openat2".to_string(), 437); - map.insert("openat".to_string(), 257); - map.insert("open_by_handle_at".to_string(), 304); - map.insert("open".to_string(), 2); - map.insert("open_tree".to_string(), 428); - map.insert("pause".to_string(), 34); - map.insert("perf_event_open".to_string(), 298); - map.insert("personality".to_string(), 135); - map.insert("pidfd_getfd".to_string(), 438); - map.insert("pidfd_open".to_string(), 434); - map.insert("pidfd_send_signal".to_string(), 424); - map.insert("pipe2".to_string(), 293); - map.insert("pipe".to_string(), 22); - map.insert("pivot_root".to_string(), 155); - map.insert("pkey_alloc".to_string(), 330); - map.insert("pkey_free".to_string(), 331); - map.insert("pkey_mprotect".to_string(), 329); - map.insert("poll".to_string(), 7); - map.insert("ppoll".to_string(), 271); - map.insert("prctl".to_string(), 157); - map.insert("pread64".to_string(), 17); - map.insert("preadv2".to_string(), 327); - map.insert("preadv".to_string(), 295); - map.insert("prlimit64".to_string(), 302); - map.insert("process_madvise".to_string(), 440); - map.insert("process_vm_readv".to_string(), 310); - map.insert("process_vm_writev".to_string(), 311); - map.insert("pselect6".to_string(), 270); - map.insert("ptrace".to_string(), 101); - map.insert("putpmsg".to_string(), 182); - map.insert("pwrite64".to_string(), 18); - map.insert("pwritev2".to_string(), 328); - map.insert("pwritev".to_string(), 296); - map.insert("query_module".to_string(), 178); - map.insert("quotactl".to_string(), 179); - map.insert("readahead".to_string(), 187); - map.insert("readlinkat".to_string(), 267); - map.insert("readlink".to_string(), 89); - map.insert("read".to_string(), 0); - map.insert("readv".to_string(), 19); - map.insert("reboot".to_string(), 169); - map.insert("recvfrom".to_string(), 45); - map.insert("recvmmsg".to_string(), 299); - map.insert("recvmsg".to_string(), 47); - map.insert("remap_file_pages".to_string(), 216); - map.insert("removexattr".to_string(), 197); - map.insert("renameat2".to_string(), 316); - map.insert("renameat".to_string(), 264); - map.insert("rename".to_string(), 82); - map.insert("request_key".to_string(), 249); - map.insert("restart_syscall".to_string(), 219); - map.insert("rmdir".to_string(), 84); - map.insert("rseq".to_string(), 334); - map.insert("rt_sigaction".to_string(), 13); - map.insert("rt_sigpending".to_string(), 127); - map.insert("rt_sigprocmask".to_string(), 14); - map.insert("rt_sigqueueinfo".to_string(), 129); - map.insert("rt_sigreturn".to_string(), 15); - map.insert("rt_sigsuspend".to_string(), 130); - map.insert("rt_sigtimedwait".to_string(), 128); - map.insert("rt_tgsigqueueinfo".to_string(), 297); - map.insert("sched_getaffinity".to_string(), 204); - map.insert("sched_getattr".to_string(), 315); - map.insert("sched_getparam".to_string(), 143); - map.insert("sched_get_priority_max".to_string(), 146); - map.insert("sched_get_priority_min".to_string(), 147); - map.insert("sched_getscheduler".to_string(), 145); - map.insert("sched_rr_get_interval".to_string(), 148); - map.insert("sched_setaffinity".to_string(), 203); - map.insert("sched_setattr".to_string(), 314); - map.insert("sched_setparam".to_string(), 142); - map.insert("sched_setscheduler".to_string(), 144); - map.insert("sched_yield".to_string(), 24); - map.insert("seccomp".to_string(), 317); - map.insert("security".to_string(), 185); - map.insert("select".to_string(), 23); - map.insert("semctl".to_string(), 66); - map.insert("semget".to_string(), 64); - map.insert("semop".to_string(), 65); - map.insert("semtimedop".to_string(), 220); - map.insert("sendfile".to_string(), 40); - map.insert("sendmmsg".to_string(), 307); - map.insert("sendmsg".to_string(), 46); - map.insert("sendto".to_string(), 44); - map.insert("setdomainname".to_string(), 171); - map.insert("setfsgid".to_string(), 123); - map.insert("setfsuid".to_string(), 122); - map.insert("setgid".to_string(), 106); - map.insert("setgroups".to_string(), 116); - map.insert("sethostname".to_string(), 170); - map.insert("setitimer".to_string(), 38); - map.insert("set_mempolicy".to_string(), 238); - map.insert("setns".to_string(), 308); - map.insert("setpgid".to_string(), 109); - map.insert("setpriority".to_string(), 141); - map.insert("setregid".to_string(), 114); - map.insert("setresgid".to_string(), 119); - map.insert("setresuid".to_string(), 117); - map.insert("setreuid".to_string(), 113); - map.insert("setrlimit".to_string(), 160); - map.insert("set_robust_list".to_string(), 273); - map.insert("setsid".to_string(), 112); - map.insert("setsockopt".to_string(), 54); - map.insert("set_thread_area".to_string(), 205); - map.insert("set_tid_address".to_string(), 218); - map.insert("settimeofday".to_string(), 164); - map.insert("setuid".to_string(), 105); - map.insert("setxattr".to_string(), 188); - map.insert("shmat".to_string(), 30); - map.insert("shmctl".to_string(), 31); - map.insert("shmdt".to_string(), 67); - map.insert("shmget".to_string(), 29); - map.insert("shutdown".to_string(), 48); - map.insert("sigaltstack".to_string(), 131); - map.insert("signalfd4".to_string(), 289); - map.insert("signalfd".to_string(), 282); - map.insert("socketpair".to_string(), 53); - map.insert("socket".to_string(), 41); - map.insert("splice".to_string(), 275); - map.insert("statfs".to_string(), 137); - map.insert("stat".to_string(), 4); - map.insert("statx".to_string(), 332); - map.insert("swapoff".to_string(), 168); - map.insert("swapon".to_string(), 167); - map.insert("symlinkat".to_string(), 266); - map.insert("symlink".to_string(), 88); - map.insert("sync_file_range".to_string(), 277); - map.insert("syncfs".to_string(), 306); - map.insert("sync".to_string(), 162); - map.insert("_sysctl".to_string(), 156); - map.insert("sysfs".to_string(), 139); - map.insert("sysinfo".to_string(), 99); - map.insert("syslog".to_string(), 103); - map.insert("tee".to_string(), 276); - map.insert("tgkill".to_string(), 234); - map.insert("timer_create".to_string(), 222); - map.insert("timer_delete".to_string(), 226); - map.insert("timerfd_create".to_string(), 283); - map.insert("timerfd_gettime".to_string(), 287); - map.insert("timerfd_settime".to_string(), 286); - map.insert("timer_getoverrun".to_string(), 225); - map.insert("timer_gettime".to_string(), 224); - map.insert("timer_settime".to_string(), 223); - map.insert("times".to_string(), 100); - map.insert("time".to_string(), 201); - map.insert("tkill".to_string(), 200); - map.insert("truncate".to_string(), 76); - map.insert("tuxcall".to_string(), 184); - map.insert("umask".to_string(), 95); - map.insert("umount2".to_string(), 166); - map.insert("uname".to_string(), 63); - map.insert("unlinkat".to_string(), 263); - map.insert("unlink".to_string(), 87); - map.insert("unshare".to_string(), 272); - map.insert("uselib".to_string(), 134); - map.insert("userfaultfd".to_string(), 323); - map.insert("ustat".to_string(), 136); - map.insert("utimensat".to_string(), 280); - map.insert("utimes".to_string(), 235); - map.insert("utime".to_string(), 132); - map.insert("vfork".to_string(), 58); - map.insert("vhangup".to_string(), 153); - map.insert("vmsplice".to_string(), 278); - map.insert("vserver".to_string(), 236); - map.insert("wait4".to_string(), 61); - map.insert("waitid".to_string(), 247); - map.insert("write".to_string(), 1); - map.insert("writev".to_string(), 20); -} diff --git a/src/seccompiler/src/types.rs b/src/seccompiler/src/types.rs new file mode 100644 index 00000000000..2035f8b8ea4 --- /dev/null +++ b/src/seccompiler/src/types.rs @@ -0,0 +1,192 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::BTreeMap; +use std::ffi::CString; +use std::str::FromStr; + +use serde::*; + +// use libseccomp::{ScmpAction, ScmpArch, ScmpCompareOp}; +use crate::bindings::*; + +/// Comparison to perform when matching a condition. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum SeccompCmpOp { + Eq, + Ge, + Gt, + Le, + Lt, + MaskedEq(u64), + Ne, +} + +/// Seccomp argument value length. +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum SeccompCmpArgLen { + /// Argument value length is 4 bytes. + Dword, + /// Argument value length is 8 bytes. + Qword, +} + +/// Condition that syscall must match in order to satisfy a rule. +#[derive(Debug, Deserialize)] +pub struct SeccompCondition { + pub index: u8, + pub op: SeccompCmpOp, + pub val: u64, + #[serde(rename = "type")] + pub val_len: SeccompCmpArgLen, +} + +impl SeccompCondition { + pub fn to_scmp_type(&self) -> scmp_arg_cmp { + match self.op { + SeccompCmpOp::Eq => { + // When using EQ libseccomp compares the whole 64 bits. In + // general this is not a problem, but for example we have + // observed musl `ioctl` to leave garbage in the upper bits of + // the `request` argument. There is a GH issue to allow 32bit + // comparisons (see + // https://github.com/seccomp/libseccomp/issues/383) but is not + // merged yet. Until that is available, do a masked comparison + // with the upper 32bits set to 0, so we will compare that `hi32 + // & 0x0 == 0`, which is always true. This costs one additional + // instruction, but will be likely be optimized away by the BPF + // JIT. + match self.val_len { + SeccompCmpArgLen::Dword => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_MASKED_EQ, + datum_a: 0x00000000FFFFFFFF, + datum_b: self.val, + }, + SeccompCmpArgLen::Qword => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_EQ, + datum_a: self.val, + datum_b: 0, + }, + } + } + SeccompCmpOp::Ge => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_GE, + datum_a: self.val, + datum_b: 0, + }, + SeccompCmpOp::Gt => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_GT, + datum_a: self.val, + datum_b: 0, + }, + SeccompCmpOp::Le => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_LE, + datum_a: self.val, + datum_b: 0, + }, + SeccompCmpOp::Lt => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_LT, + datum_a: self.val, + datum_b: 0, + }, + SeccompCmpOp::Ne => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_NE, + datum_a: self.val, + datum_b: 0, + }, + + SeccompCmpOp::MaskedEq(m) => scmp_arg_cmp { + arg: self.index as u32, + op: scmp_compare::SCMP_CMP_MASKED_EQ, + datum_a: m, + datum_b: self.val, + }, + } + } +} + +/// Actions that `seccomp` can apply to process calling a syscall. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum SeccompAction { + Allow, + Errno(u16), + KillThread, + KillProcess, + Log, + Trace(u16), + Trap, +} + +impl SeccompAction { + pub fn to_scmp_type(&self) -> u32 { + match self { + SeccompAction::Allow => SCMP_ACT_ALLOW, + SeccompAction::Errno(e) => SCMP_ACT_ERRNO(*e), + SeccompAction::KillThread => SCMP_ACT_KILL_THREAD, + SeccompAction::KillProcess => SCMP_ACT_KILL_PROCESS, + SeccompAction::Log => SCMP_ACT_LOG, + SeccompAction::Trace(t) => SCMP_ACT_TRACE(*t), + SeccompAction::Trap => SCMP_ACT_TRAP, + } + } +} + +/// Rule that `seccomp` attempts to match for a syscall. +/// +/// If all conditions match then rule gets matched. +/// The action of the first rule that matches will be applied to the calling process. +/// If no rule matches the default action is applied. +#[derive(Debug, Deserialize)] +pub struct SyscallRule { + pub syscall: CString, + pub args: Option>, +} + +/// Filter containing rules assigned to syscall numbers. +#[derive(Debug, Deserialize)] +pub struct Filter { + pub default_action: SeccompAction, + pub filter_action: SeccompAction, + pub filter: Vec, +} + +/// Deserializable object that represents the Json filter file. +#[derive(Debug, Deserialize)] +pub struct BpfJson(pub BTreeMap); + +/// Supported target architectures. +#[derive(Debug)] +pub enum TargetArch { + X86_64, + Aarch64, +} + +impl TargetArch { + pub fn to_scmp_type(&self) -> u32 { + match self { + TargetArch::X86_64 => SCMP_ARCH_X86_64, + TargetArch::Aarch64 => SCMP_ARCH_AARCH64, + } + } +} + +impl FromStr for TargetArch { + type Err = String; + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "x86_64" => Ok(TargetArch::X86_64), + "aarch64" => Ok(TargetArch::Aarch64), + _ => Err(s.to_string()), + } + } +} diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 8773198c002..4e1cf8eed73 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -31,7 +31,6 @@ log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -seccompiler = { path = "../seccompiler" } semver = { version = "1.0.24", features = ["serde"] } serde = { version = "1.0.217", features = ["derive", "rc"] } serde_json = "1.0.135" diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 6131e248d91..82bfa635032 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -19,7 +19,6 @@ use linux_loader::loader::elf::Elf as Loader; #[cfg(target_arch = "aarch64")] use linux_loader::loader::pe::PE as Loader; use linux_loader::loader::KernelLoader; -use seccompiler::BpfThreadMap; use userfaultfd::Uffd; use utils::time::TimestampUs; use vm_memory::ReadVolatile; @@ -63,6 +62,7 @@ use crate::gdb; use crate::logger::{debug, error}; use crate::persist::{MicrovmState, MicrovmStateError}; use crate::resources::VmResources; +use crate::seccomp::BpfThreadMap; use crate::snapshot::Persist; use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootConfig; @@ -372,7 +372,7 @@ pub fn build_microvm_for_boot( // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters // altogether is the desired behaviour. // Keep this as the last step before resuming vcpus. - seccompiler::apply_filter( + crate::seccomp::apply_filter( seccomp_filters .get("vmm") .ok_or_else(|| MissingSeccompFilters("vmm".to_string()))?, @@ -443,7 +443,7 @@ pub enum BuildMicrovmFromSnapshotError { /// Failed to apply VMM secccomp filter as none found. MissingVmmSeccompFilters, /// Failed to apply VMM secccomp filter: {0} - SeccompFiltersInternal(#[from] seccompiler::InstallationError), + SeccompFiltersInternal(#[from] crate::seccomp::InstallationError), /// Failed to restore ACPI device manager: {0} ACPIDeviManager(#[from] ACPIDeviceManagerRestoreError), /// VMGenID update failed: {0} @@ -559,7 +559,7 @@ pub fn build_microvm_from_snapshot( // Load seccomp filters for the VMM thread. // Keep this as the last step of the building process. - seccompiler::apply_filter( + crate::seccomp::apply_filter( seccomp_filters .get("vmm") .ok_or(BuildMicrovmFromSnapshotError::MissingVmmSeccompFilters)?, diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 6a28e14f26b..77c0018c55a 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -97,7 +97,7 @@ pub mod resources; /// microVM RPC API adapters. pub mod rpc_interface; /// Seccomp filter utilities. -pub mod seccomp_filters; +pub mod seccomp; /// Signal handling utilities. pub mod signal_handler; /// Serialization and deserialization facilities @@ -122,7 +122,7 @@ use device_manager::acpi::ACPIDeviceManager; use device_manager::resources::ResourceAllocator; use devices::acpi::vmgenid::VmGenIdError; use event_manager::{EventManager as BaseEventManager, EventOps, Events, MutEventSubscriber}; -use seccompiler::BpfProgram; +use seccomp::BpfProgram; use userfaultfd::Uffd; use vmm_sys_util::epoll::EventSet; use vmm_sys_util::eventfd::EventFd; @@ -225,7 +225,7 @@ pub enum VmmError { /// Cannot add a device to the MMIO Bus. {0} RegisterMMIODevice(device_manager::mmio::MmioError), /// Cannot install seccomp filters: {0} - SeccompFilters(seccompiler::InstallationError), + SeccompFilters(seccomp::InstallationError), /// Error writing to the serial console: {0} Serial(io::Error), /// Error creating timer fd: {0} diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 3479e0b6309..1feef41ec30 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -11,7 +11,6 @@ use std::os::unix::net::UnixStream; use std::path::Path; use std::sync::{Arc, Mutex}; -use seccompiler::BpfThreadMap; use semver::Version; use serde::{Deserialize, Serialize}; use userfaultfd::{FeatureFlags, Uffd, UffdBuilder}; @@ -28,6 +27,7 @@ use crate::cpu_config::x86_64::cpuid::CpuidTrait; use crate::device_manager::persist::{ACPIDeviceManagerState, DevicePersistError, DeviceStates}; use crate::logger::{info, warn}; use crate::resources::VmResources; +use crate::seccomp::BpfThreadMap; use crate::snapshot::Snapshot; use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootSourceConfig; diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index b0c95529f46..60a046f7e89 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -4,7 +4,6 @@ use std::fmt::{self, Debug}; use std::sync::{Arc, Mutex, MutexGuard}; -use seccompiler::BpfThreadMap; use serde_json::Value; use utils::time::{get_time_us, ClockType}; @@ -18,6 +17,7 @@ use crate::logger::{info, warn, LoggerConfig, *}; use crate::mmds::data_store::{self, Mmds}; use crate::persist::{CreateSnapshotError, RestoreFromSnapshotError, VmInfo}; use crate::resources::VmmConfig; +use crate::seccomp::BpfThreadMap; use crate::vmm_config::balloon::{ BalloonConfigError, BalloonDeviceConfig, BalloonStats, BalloonUpdateConfig, BalloonUpdateStatsConfig, @@ -852,12 +852,11 @@ impl RuntimeApiController { mod tests { use std::path::PathBuf; - use seccompiler::BpfThreadMap; - use super::*; use crate::builder::tests::default_vmm; use crate::devices::virtio::block::CacheType; use crate::mmds::data_store::MmdsVersion; + use crate::seccomp::BpfThreadMap; use crate::vmm_config::snapshot::{MemBackendConfig, MemBackendType}; use crate::HTTP_MAX_PAYLOAD_SIZE; diff --git a/src/vmm/src/seccomp.rs b/src/vmm/src/seccomp.rs new file mode 100644 index 00000000000..6948754f51a --- /dev/null +++ b/src/vmm/src/seccomp.rs @@ -0,0 +1,238 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::HashMap; +use std::io::Read; +use std::sync::Arc; + +use bincode::{DefaultOptions, Error as BincodeError, Options}; + +/// Each BPF instruction is 8 bytes long and 4 byte aligned. +/// This alignment needs to be satisfied in order for a BPF code to be accepted +/// by the syscalls. Using u64 here is is safe as it has same size and even bigger alignment. +pub type BpfInstruction = u64; + +/// Program made up of a sequence of BPF instructions. +pub type BpfProgram = Vec; + +/// Reference to program made up of a sequence of BPF instructions. +pub type BpfProgramRef<'a> = &'a [BpfInstruction]; + +/// Type that associates a thread category to a BPF program. +pub type BpfThreadMap = HashMap>; + +/// Retrieve empty seccomp filters. +pub fn get_empty_filters() -> BpfThreadMap { + let mut map = BpfThreadMap::new(); + map.insert("vmm".to_string(), Arc::new(vec![])); + map.insert("api".to_string(), Arc::new(vec![])); + map.insert("vcpu".to_string(), Arc::new(vec![])); + map +} + +/// Binary filter deserialization errors. +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum DeserializationError { + /// Bincode deserialization failed: {0} + Bincode(BincodeError), +} + +/// Deserialize binary with bpf filters +pub fn deserialize_binary( + reader: R, + bytes_limit: Option, +) -> Result { + let result = match bytes_limit { + Some(limit) => DefaultOptions::new() + .with_fixint_encoding() + .allow_trailing_bytes() + .with_limit(limit) + .deserialize_from::>(reader), + // No limit is the default. + None => bincode::deserialize_from::>(reader), + } + .map_err(DeserializationError::Bincode)?; + + Ok(result + .into_iter() + .map(|(k, v)| (k.to_lowercase(), Arc::new(v))) + .collect()) +} + +/// Filter installation errors. +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum InstallationError { + /// Filter length exceeds the maximum size of {BPF_MAX_LEN:} instructions + FilterTooLarge, + /// prctl` syscall failed with error code: {0} + Prctl(i32), +} + +/// The maximum seccomp-BPF program length allowed by the linux kernel. +pub const BPF_MAX_LEN: usize = 4096; + +/// BPF structure definition for filter array. +/// See /usr/include/linux/filter.h . +#[repr(C)] +#[derive(Debug)] +struct SockFprog { + len: u16, + filter: *const BpfInstruction, +} + +/// Apply bpf filter. +pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<(), InstallationError> { + // If the program is empty, don't install the filter. + if bpf_filter.is_empty() { + return Ok(()); + } + + // If the program length is greater than the limit allowed by the kernel, + // fail quickly. Otherwise, `prctl` will give a more cryptic error code. + if BPF_MAX_LEN < bpf_filter.len() { + return Err(InstallationError::FilterTooLarge); + } + + let bpf_filter_len = + u16::try_from(bpf_filter.len()).map_err(|_| InstallationError::FilterTooLarge)?; + + // SAFETY: Safe because the parameters are valid. + unsafe { + { + let rc = libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + if rc != 0 { + return Err(InstallationError::Prctl(*libc::__errno_location())); + } + } + + let bpf_prog = SockFprog { + len: bpf_filter_len, + filter: bpf_filter.as_ptr(), + }; + let bpf_prog_ptr = &bpf_prog as *const SockFprog; + { + let rc = libc::prctl( + libc::PR_SET_SECCOMP, + libc::SECCOMP_MODE_FILTER, + bpf_prog_ptr, + ); + if rc != 0 { + return Err(InstallationError::Prctl(*libc::__errno_location())); + } + } + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + #![allow(clippy::undocumented_unsafe_blocks)] + + use std::collections::HashMap; + use std::sync::Arc; + use std::thread; + + use super::*; + + #[test] + fn test_deserialize_binary() { + // Malformed bincode binary. + { + let data = "adassafvc".to_string(); + deserialize_binary(data.as_bytes(), None).unwrap_err(); + } + + // Test that the binary deserialization is correct, and that the thread keys + // have been lowercased. + { + let bpf_prog = vec![0; 2]; + let mut filter_map: HashMap = HashMap::new(); + filter_map.insert("VcpU".to_string(), bpf_prog.clone()); + let bytes = bincode::serialize(&filter_map).unwrap(); + + let mut expected_res = BpfThreadMap::new(); + expected_res.insert("vcpu".to_string(), Arc::new(bpf_prog)); + assert_eq!(deserialize_binary(&bytes[..], None).unwrap(), expected_res); + } + + // Test deserialization with binary_limit. + { + let bpf_prog = vec![0; 2]; + + let mut filter_map: HashMap = HashMap::new(); + filter_map.insert("t1".to_string(), bpf_prog.clone()); + + let bytes = bincode::serialize(&filter_map).unwrap(); + + // Binary limit too low. + assert!(matches!( + deserialize_binary(&bytes[..], Some(20)).unwrap_err(), + DeserializationError::Bincode(error) + if error.to_string() == "the size limit has been reached" + )); + + let mut expected_res = BpfThreadMap::new(); + expected_res.insert("t1".to_string(), Arc::new(bpf_prog)); + + // Correct binary limit. + assert_eq!( + deserialize_binary(&bytes[..], Some(50)).unwrap(), + expected_res + ); + } + } + + #[test] + fn test_filter_apply() { + // Test filter too large. + thread::spawn(|| { + let filter: BpfProgram = vec![0; 5000]; + + // Apply seccomp filter. + assert_eq!( + apply_filter(&filter).unwrap_err(), + InstallationError::FilterTooLarge + ); + }) + .join() + .unwrap(); + + // Test empty filter. + thread::spawn(|| { + let filter: BpfProgram = vec![]; + + assert_eq!(filter.len(), 0); + + let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; + assert_eq!(seccomp_level, 0); + + apply_filter(&filter).unwrap(); + + // test that seccomp level remains 0 on failure. + let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; + assert_eq!(seccomp_level, 0); + }) + .join() + .unwrap(); + + // Test invalid BPF code. + thread::spawn(|| { + let filter = vec![0xFF; 1]; + + let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; + assert_eq!(seccomp_level, 0); + + assert_eq!( + apply_filter(&filter).unwrap_err(), + InstallationError::Prctl(22) + ); + + // test that seccomp level remains 0 on failure. + let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; + assert_eq!(seccomp_level, 0); + }) + .join() + .unwrap(); + } +} diff --git a/src/vmm/src/seccomp_filters.rs b/src/vmm/src/seccomp_filters.rs deleted file mode 100644 index aabdc1ef2c1..00000000000 --- a/src/vmm/src/seccomp_filters.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -use std::sync::Arc; - -use seccompiler::BpfThreadMap; - -/// Retrieve empty seccomp filters. -pub fn get_empty_filters() -> BpfThreadMap { - let mut map = BpfThreadMap::new(); - map.insert("vmm".to_string(), Arc::new(vec![])); - map.insert("api".to_string(), Arc::new(vec![])); - map.insert("vcpu".to_string(), Arc::new(vec![])); - map -} diff --git a/src/vmm/src/signal_handler.rs b/src/vmm/src/signal_handler.rs index 5bcfd41fd06..ac4befcb3d1 100644 --- a/src/vmm/src/signal_handler.rs +++ b/src/vmm/src/signal_handler.rs @@ -177,7 +177,6 @@ mod tests { use std::{process, thread}; use libc::syscall; - use seccompiler::sock_filter; use super::*; @@ -186,11 +185,6 @@ mod tests { let child = thread::spawn(move || { register_signal_handlers().unwrap(); - let filter = make_test_seccomp_bpf_filter(); - - seccompiler::apply_filter(&filter).unwrap(); - assert_eq!(METRICS.seccomp.num_faults.fetch(), 0); - // Call the forbidden `SYS_mkdirat`. unsafe { libc::syscall(libc::SYS_mkdirat, "/foo/bar\0") }; @@ -238,7 +232,6 @@ mod tests { }); child.join().unwrap(); - assert!(METRICS.seccomp.num_faults.fetch() >= 1); assert!(METRICS.signals.sigbus.fetch() >= 1); assert!(METRICS.signals.sigsegv.fetch() >= 1); assert!(METRICS.signals.sigxfsz.fetch() >= 1); @@ -247,141 +240,4 @@ mod tests { assert!(METRICS.signals.sighup.fetch() >= 1); assert!(METRICS.signals.sigill.fetch() >= 1); } - - fn make_test_seccomp_bpf_filter() -> Vec { - // Create seccomp filter that allows all syscalls, except for `SYS_mkdirat`. - // For some reason, directly calling `SYS_kill` with SIGSYS, like we do with the - // other signals, results in an error. Probably because of the way `cargo test` is - // handling signals. - #[cfg(target_arch = "aarch64")] - #[allow(clippy::unreadable_literal)] - let bpf_filter = vec![ - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 4, - }, - sock_filter { - code: 21, - jt: 1, - jf: 0, - k: 3221225655, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 0, - }, - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 0, - }, - sock_filter { - code: 21, - jt: 0, - jf: 1, - k: 34, - }, - sock_filter { - code: 5, - jt: 0, - jf: 0, - k: 1, - }, - sock_filter { - code: 5, - jt: 0, - jf: 0, - k: 2, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 196608, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 2147418112, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 2147418112, - }, - ]; - #[cfg(target_arch = "x86_64")] - #[allow(clippy::unreadable_literal)] - let bpf_filter = vec![ - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 4, - }, - sock_filter { - code: 21, - jt: 1, - jf: 0, - k: 3221225534, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 0, - }, - sock_filter { - code: 32, - jt: 0, - jf: 0, - k: 0, - }, - sock_filter { - code: 21, - jt: 0, - jf: 1, - k: 258, - }, - sock_filter { - code: 5, - jt: 0, - jf: 0, - k: 1, - }, - sock_filter { - code: 5, - jt: 0, - jf: 0, - k: 2, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 196608, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 2147418112, - }, - sock_filter { - code: 6, - jt: 0, - jf: 0, - k: 2147418112, - }, - ]; - - bpf_filter - } } diff --git a/src/vmm/src/test_utils/mod.rs b/src/vmm/src/test_utils/mod.rs index f90ba7fbd0c..1ba79a55231 100644 --- a/src/vmm/src/test_utils/mod.rs +++ b/src/vmm/src/test_utils/mod.rs @@ -10,7 +10,7 @@ use vmm_sys_util::tempdir::TempDir; use crate::builder::build_microvm_for_boot; use crate::resources::VmResources; -use crate::seccomp_filters::get_empty_filters; +use crate::seccomp::get_empty_filters; use crate::test_utils::mock_resources::{MockBootSourceConfig, MockVmConfig, MockVmResources}; use crate::vmm_config::boot_source::BootSourceConfig; use crate::vmm_config::instance_info::InstanceInfo; diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 73779fbd928..ddfeda21b4c 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -19,7 +19,6 @@ use kvm_ioctls::VcpuExit; use kvm_ioctls::VcpuFd; use libc::{c_int, c_void, siginfo_t}; use log::{error, info, warn}; -use seccompiler::{BpfProgram, BpfProgramRef}; use vmm_sys_util::errno; use vmm_sys_util::eventfd::EventFd; @@ -27,6 +26,7 @@ use crate::cpu_config::templates::{CpuConfiguration, GuestConfigError}; #[cfg(feature = "gdb")] use crate::gdb::target::{get_raw_tid, GdbTargetError}; use crate::logger::{IncMetric, METRICS}; +use crate::seccomp::{BpfProgram, BpfProgramRef}; use crate::utils::signal::{register_signal_handler, sigrtmin, Killable}; use crate::utils::sm::StateMachine; use crate::vstate::vm::Vm; @@ -288,7 +288,7 @@ impl Vcpu { // Load seccomp filters for this vCPU thread. // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters // altogether is the desired behaviour. - if let Err(err) = seccompiler::apply_filter(seccomp_filter) { + if let Err(err) = crate::seccomp::apply_filter(seccomp_filter) { panic!( "Failed to set the requested seccomp filters on vCPU {}: Error: {}", self.kvm_vcpu.index, err @@ -773,7 +773,7 @@ pub(crate) mod tests { use crate::builder::StartMicrovmError; use crate::devices::bus::DummyDevice; use crate::devices::BusDevice; - use crate::seccomp_filters::get_empty_filters; + use crate::seccomp::get_empty_filters; use crate::utils::signal::validate_signal_num; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuError as EmulationError; diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index 4312c6345db..40eab05c4a4 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -12,7 +12,7 @@ use vmm::resources::VmResources; use vmm::rpc_interface::{ LoadSnapshotError, PrebootApiController, RuntimeApiController, VmmAction, VmmActionError, }; -use vmm::seccomp_filters::get_empty_filters; +use vmm::seccomp::get_empty_filters; use vmm::snapshot::Snapshot; #[cfg(target_arch = "x86_64")] use vmm::test_utils::dirty_tracking_vmm; From acee69f3d1d130bdd6531ed9782c15e7a86e919a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 16 Dec 2024 17:21:23 +0100 Subject: [PATCH 158/464] devtool: remove obsolete commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we depend on libseccomp in the previous commit, these commands to update the syscall table are no longer needed. Signed-off-by: Pablo Barbáchano --- tools/devtool | 137 -------------------------------------------------- 1 file changed, 137 deletions(-) diff --git a/tools/devtool b/tools/devtool index 2ab7969484b..29434bf8100 100755 --- a/tools/devtool +++ b/tools/devtool @@ -375,12 +375,6 @@ cmd_help() { echo " This should be used as the last step in every commit, to ensure that the" echo " Rust style tests pass." echo "" - echo " generate_syscall_tables " - echo " Generates the syscall tables for seccompiler, according to a given kernel version." - echo " Release candidate (rc) linux versions are not allowed." - echo " Outputs a rust file for each supported arch: src/seccompiler/src/syscall_table/{arch}.rs" - echo " Supported architectures: x86_64 and aarch64." - echo "" echo " install [-p|--path] [--debug|--release]" echo " Install firecracker, jailer and seccomp binaries to /usr/local/bin or a given path." echo " Only the musl linked binaries are supported." @@ -1029,137 +1023,6 @@ cmd_checkenv() { check_vulns } -generate_syscall_table_x86_64() { - path_to_rust_file="$FC_ROOT_DIR/src/seccompiler/src/syscall_table/x86_64.rs" - - echo "$header" > $path_to_rust_file - - # the table for x86_64 is nicely formatted here: linux/arch/x86/entry/syscalls/syscall_64.tbl - cat linux/arch/x86/entry/syscalls/syscall_64.tbl | grep -v "^#" | grep -v -e '^$' |\ - awk '{print $2,$3,$1}' | grep -v "^x32" |\ - awk '{print " map.insert(\""$2"\".to_string(), "$3");"}' | sort >> $path_to_rust_file - - echo "$footer" >> $path_to_rust_file - - say "Generated at: $path_to_rust_file" -} - -generate_syscall_table_aarch64() { - path_to_rust_file="$FC_ROOT_DIR/src/seccompiler/src/syscall_table/aarch64.rs" - - # filter for substituting `#define`s that point to other macros; - # values taken from linux/include/uapi/asm-generic/unistd.h - replace+='s/__NR3264_fadvise64/223/;' - replace+='s/__NR3264_fcntl/25/;' - replace+='s/__NR3264_fstatat/79/;' - replace+='s/__NR3264_fstatfs/44/;' - replace+='s/__NR3264_fstat/80/;' - replace+='s/__NR3264_ftruncate/46/;' - replace+='s/__NR3264_lseek/62/;' - replace+='s/__NR3264_sendfile/71/;' - replace+='s/__NR3264_statfs/43/;' - replace+='s/__NR3264_truncate/45/;' - replace+='s/__NR3264_mmap/222/;' - - echo "$header" > $path_to_rust_file - - # run the gcc command in the Docker container (to make sure that we have gcc installed) - # the aarch64 syscall table is not located in a .tbl file, like x86; we run gcc's - # pre-processor to extract the numeric constants from header files. - run_devctr \ - --user "$(id -u):$(id -g)" \ - --workdir "$CTR_KERNEL_DIR" \ - -- \ - gcc -Ilinux/include/uapi -E -dM -D__ARCH_WANT_RENAMEAT\ - -D__BITS_PER_LONG=64\ - linux/arch/arm64/include/uapi/asm/unistd.h |\ - grep "#define __NR_" | grep -v "__NR_syscalls" |\ - grep -v "__NR_arch_specific_syscall" |\ - awk -F '__NR_' '{print $2}' |\ - sed $replace |\ - awk '{ print " map.insert(\""$1"\".to_string(), "$2");" }' |\ - sort -d >> $path_to_rust_file - ret=$? - - [ $ret -ne 0 ] && return $ret - - echo "$footer" >> $path_to_rust_file - - say "Generated at: $path_to_rust_file" -} - -cmd_generate_syscall_tables() { - # Parse any command line args. - while [ $# -gt 0 ]; do - case "$1" in - "-h"|"--help") { cmd_help; exit 1; } ;; - *) { kernel_version="$1"; break; } ;; - esac - shift - done - - validate_kernel_version "$kernel_version" - - kernel_major=v$(echo ${kernel_version} | cut -d . -f 1).x - kernel_baseurl=https://www.kernel.org/pub/linux/kernel/${kernel_major} - kernel_archive=linux-${kernel_version}.tar.xz - - ensure_devctr - - # Create the kernel clone directory - rm -rf "$KERNEL_DIR" - create_dir "$KERNEL_DIR" - cd "$KERNEL_DIR" - - say "Fetching linux kernel..." - - # Get sha256 checksum. - curl -fsSLO ${kernel_baseurl}/sha256sums.asc && \ - kernel_sha256=$(grep ${kernel_archive} sha256sums.asc | cut -d ' ' -f 1) - # Get kernel archive. - curl -fsSLO "$kernel_baseurl/$kernel_archive" && \ - # Verify checksum. - echo "${kernel_sha256} ${kernel_archive}" | sha256sum -c - && \ - # Decompress the kernel source. - xz -d "${kernel_archive}" && \ - cat linux-${kernel_version}.tar | tar -x && mv linux-${kernel_version} linux - - ret=$? - [ $ret -ne 0 ] && return $ret - - # rust file header - read -r -d '' header << EOM -// Copyright $(date +"%Y") Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -// This file is auto-generated by \`tools/devtool generate_syscall_tables\`. -// Do NOT manually edit! -// Generated at: $(date) -// Kernel version: $kernel_version - -use std::collections::HashMap; - -pub(crate) fn make_syscall_table(map: &mut HashMap) { -EOM - - # rust file footer - read -r -d '' footer << EOM -} - -EOM - - # generate syscall table for x86_64 - say "Generating table for x86_64..." - generate_syscall_table_x86_64 $header $footer - - # generate syscall table for aarch64 - say "Generating table for aarch64..." - generate_syscall_table_aarch64 $header $footer - - ret=$? - [ $ret -ne 0 ] && return $ret -} - cmd_install() { # By default we install release/musl binaries. profile="release" From 66263bde82380bdd57166febdf324639b1b28576 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 29 Nov 2024 16:17:19 +0000 Subject: [PATCH 159/464] refactor(seccomp): replace deprecated `prctl` with `syscall` According to https://www.man7.org/linux/man-pages/man2/PR_SET_SECCOMP.2const.html using `prctl` for setting seccomp filer is deprecated, so switch to using `syscall` instead. Signed-off-by: Egor Lazarchuk --- src/vmm/src/seccomp.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/seccomp.rs b/src/vmm/src/seccomp.rs index 6948754f51a..f62845bc800 100644 --- a/src/vmm/src/seccomp.rs +++ b/src/vmm/src/seccomp.rs @@ -111,9 +111,10 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<(), InstallationError> }; let bpf_prog_ptr = &bpf_prog as *const SockFprog; { - let rc = libc::prctl( - libc::PR_SET_SECCOMP, - libc::SECCOMP_MODE_FILTER, + let rc = libc::syscall( + libc::SYS_seccomp, + libc::SECCOMP_SET_MODE_FILTER, + 0, bpf_prog_ptr, ); if rc != 0 { From a00964eef5a8d1e1c169137a4cb31ee87ca6d862 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 11 Dec 2024 12:41:15 +0000 Subject: [PATCH 160/464] refactor: use std::io::Error when setting seccomp Replace __errno_location() with std::io::Error::last_os_error() as a more standard of getting errno value. Signed-off-by: Egor Lazarchuk --- src/vmm/src/seccomp.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vmm/src/seccomp.rs b/src/vmm/src/seccomp.rs index f62845bc800..02fbf01b2dc 100644 --- a/src/vmm/src/seccomp.rs +++ b/src/vmm/src/seccomp.rs @@ -60,12 +60,12 @@ pub fn deserialize_binary( } /// Filter installation errors. -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +#[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum InstallationError { /// Filter length exceeds the maximum size of {BPF_MAX_LEN:} instructions FilterTooLarge, /// prctl` syscall failed with error code: {0} - Prctl(i32), + Prctl(std::io::Error), } /// The maximum seccomp-BPF program length allowed by the linux kernel. @@ -101,7 +101,7 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<(), InstallationError> { let rc = libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); if rc != 0 { - return Err(InstallationError::Prctl(*libc::__errno_location())); + return Err(InstallationError::Prctl(std::io::Error::last_os_error())); } } @@ -118,7 +118,7 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<(), InstallationError> bpf_prog_ptr, ); if rc != 0 { - return Err(InstallationError::Prctl(*libc::__errno_location())); + return Err(InstallationError::Prctl(std::io::Error::last_os_error())); } } } @@ -191,10 +191,10 @@ mod tests { let filter: BpfProgram = vec![0; 5000]; // Apply seccomp filter. - assert_eq!( + assert!(matches!( apply_filter(&filter).unwrap_err(), InstallationError::FilterTooLarge - ); + )); }) .join() .unwrap(); @@ -224,10 +224,10 @@ mod tests { let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; assert_eq!(seccomp_level, 0); - assert_eq!( + assert!(matches!( apply_filter(&filter).unwrap_err(), - InstallationError::Prctl(22) - ); + InstallationError::Prctl(_) + )); // test that seccomp level remains 0 on failure. let seccomp_level = unsafe { libc::prctl(libc::PR_GET_SECCOMP) }; From f680208cd5ae74aa07952fc18638879eac84313f Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 11 Dec 2024 13:54:46 +0000 Subject: [PATCH 161/464] refactor: replace DeserializationError with type alias The error enum had only 1 element and we can replace it with alias for simplicity. Signed-off-by: Egor Lazarchuk --- src/vmm/src/seccomp.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/vmm/src/seccomp.rs b/src/vmm/src/seccomp.rs index 02fbf01b2dc..3da974e6027 100644 --- a/src/vmm/src/seccomp.rs +++ b/src/vmm/src/seccomp.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use std::io::Read; use std::sync::Arc; -use bincode::{DefaultOptions, Error as BincodeError, Options}; +use bincode::{DefaultOptions, Options}; /// Each BPF instruction is 8 bytes long and 4 byte aligned. /// This alignment needs to be satisfied in order for a BPF code to be accepted @@ -21,6 +21,9 @@ pub type BpfProgramRef<'a> = &'a [BpfInstruction]; /// Type that associates a thread category to a BPF program. pub type BpfThreadMap = HashMap>; +/// Binary filter deserialization errors. +pub type DeserializationError = bincode::Error; + /// Retrieve empty seccomp filters. pub fn get_empty_filters() -> BpfThreadMap { let mut map = BpfThreadMap::new(); @@ -30,13 +33,6 @@ pub fn get_empty_filters() -> BpfThreadMap { map } -/// Binary filter deserialization errors. -#[derive(Debug, thiserror::Error, displaydoc::Display)] -pub enum DeserializationError { - /// Bincode deserialization failed: {0} - Bincode(BincodeError), -} - /// Deserialize binary with bpf filters pub fn deserialize_binary( reader: R, @@ -50,8 +46,7 @@ pub fn deserialize_binary( .deserialize_from::>(reader), // No limit is the default. None => bincode::deserialize_from::>(reader), - } - .map_err(DeserializationError::Bincode)?; + }?; Ok(result .into_iter() @@ -169,7 +164,7 @@ mod tests { // Binary limit too low. assert!(matches!( deserialize_binary(&bytes[..], Some(20)).unwrap_err(), - DeserializationError::Bincode(error) + error if error.to_string() == "the size limit has been reached" )); From bd42beb28c41d5a0b0d9a88963fdada4c1f1ccce Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 11 Dec 2024 14:57:58 +0000 Subject: [PATCH 162/464] chore: add libseccomp update to CHANGELOG Add a note about updating backend for seccompiler to libseccomp. Signed-off-by: Egor Lazarchuk --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e402b85ad43..c993dfe8bb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to unnecessary fields (`max_connections` and `max_pending_resets`) from the snapshot format, bumping the snapshot version to 5.0.0. Users need to regenerate snapshots. +- [#4926](https://github.com/firecracker-microvm/firecracker/pull/4926): Replace + underlying implementation for seccompiler from in house one in favor of + `libseccomp` which produces smaller and more optimized BPF code. ### Deprecated From 104d5d0b1b6ccb07b4d6f41ac09e2bcaaa61e769 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 11 Dec 2024 16:04:26 +0000 Subject: [PATCH 163/464] chore: add additional path for libseccomp lib Kani on x86 for some reason cannot find libseccomp by default, so we add additional path to the build.rs Signed-off-by: Egor Lazarchuk --- src/seccompiler/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/seccompiler/build.rs b/src/seccompiler/build.rs index 69878f1f31b..d0d2a30e39e 100644 --- a/src/seccompiler/build.rs +++ b/src/seccompiler/build.rs @@ -2,5 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 fn main() { + println!("cargo::rustc-link-search=/usr/local/lib"); println!("cargo::rustc-link-lib=seccomp"); } From c18254467b695a71631d9896df13dcf3a9fd4db8 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 9 Jan 2025 17:04:25 +0000 Subject: [PATCH 164/464] chore: update NOTICE with info about libseccomp usage Add a note about libseccomp usage in Firecracker build process and in the seccomp-bin. Signed-off-by: Egor Lazarchuk --- NOTICE | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NOTICE b/NOTICE index ff113a0f1a4..f2daaa7be8d 100644 --- a/NOTICE +++ b/NOTICE @@ -5,3 +5,8 @@ SPDX-License-Identifier: Apache-2.0 Portions Copyright 2017 The Chromium OS Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the THIRD-PARTY file. + +The Firecracker release bundle includes libseccomp which is available +under the LGPLv2.1 license. This is used in the Firecracker build process +to produce cBPF bytecode that is shipped alongside Firecracker for use by +the Linux kernel. From 3afaf949ed220570cafe0ba84ce7580fe469884b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 10 Jan 2025 12:55:09 +0000 Subject: [PATCH 165/464] Drop `Serialize` implementation on `MachineConfigUpdate` We never make us of this, and I do not see where this ever _could_ be useful. Signed-off-by: Patrick Roy --- src/vmm/src/vmm_config/machine_config.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 8eee91c88be..58091af2b54 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -129,30 +129,28 @@ impl Default for MachineConfig { /// All fields are optional, but at least one needs to be specified. /// If a field is `Some(value)` then we assume an update is requested /// for that field. -#[derive(Clone, Default, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Default, Debug, PartialEq, Eq, Deserialize)] #[serde(deny_unknown_fields)] pub struct MachineConfigUpdate { /// Number of vcpu to start. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub vcpu_count: Option, /// The memory size in MiB. - #[serde(skip_serializing_if = "Option::is_none")] pub mem_size_mib: Option, /// Enables or disabled SMT. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub smt: Option, /// A CPU template that it is used to filter the CPU features exposed to the guest. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub cpu_template: Option, /// Enables or disables dirty page tracking. Enabling allows incremental snapshots. - #[serde(skip_serializing_if = "Option::is_none")] pub track_dirty_pages: Option, /// Configures what page size Firecracker should use to back guest memory. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub huge_pages: Option, /// GDB socket address. #[cfg(feature = "gdb")] - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub gdb_socket_path: Option, } From 9cf1e6deeacfe2e6f0b85a501213cbbdb4434698 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 10 Jan 2025 12:59:11 +0000 Subject: [PATCH 166/464] fix: make `mem_size_mib` and `track_dirty_pages` optional This makes these fields optional in PATCH /machine-config requests. The comment on this structure says that all fields should be optional, and I dont quite see why these two should be different. Thus, add `serde(default)` to avoid forcing customers to explicitly set them to `null` if they do not want to update these parts of the machine config. Signed-off-by: Patrick Roy --- CHANGELOG.md | 4 ++++ src/vmm/src/vmm_config/machine_config.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c993dfe8bb2..138ccd20079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ and this project adheres to - [#4916](https://github.com/firecracker-microvm/firecracker/pull/4916): Fixed `IovDeque` implementation to work with any host page size. This fixes virtio-net device on non 4K host kernels. +- [#4991](https://github.com/firecracker-microvm/firecracker/pull/4991): Fixed + `mem_size_mib` and `track_dirty_pages` being mandatory for all + `PATCH /machine-config` requests. Now, they can be omitted which leaves these + parts of the machine configuration unchanged. ## [1.10.1] diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 58091af2b54..482fcfdd08f 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -136,6 +136,7 @@ pub struct MachineConfigUpdate { #[serde(default)] pub vcpu_count: Option, /// The memory size in MiB. + #[serde(default)] pub mem_size_mib: Option, /// Enables or disabled SMT. #[serde(default)] @@ -144,6 +145,7 @@ pub struct MachineConfigUpdate { #[serde(default)] pub cpu_template: Option, /// Enables or disables dirty page tracking. Enabling allows incremental snapshots. + #[serde(default)] pub track_dirty_pages: Option, /// Configures what page size Firecracker should use to back guest memory. #[serde(default)] From 3793b9949774cf1d11abb2ef664664b8f40958a0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 10 Jan 2025 13:20:30 +0000 Subject: [PATCH 167/464] refactor: Get rid of `VmConfig` This struct is almost a 1:1 duplication of `struct MachineConfig`, with only a single deviation when it comes to CPU template handling (see below). This makes it very annoying to add new fields to the /machine-config endpoint, because counter-intuitively we have to hand-edit at least 3 structs to add new fields to. We can get rid of this duplication by merging VmConfig and MachineConfig into just `MachineConfig` (that's what the endpoint is called, so having the struct be the same makes sense). We now need to handle a bit of nasty-ness when it comes to CPU templates, because /machine-config can only be used for specifying static cpu templates, while a VmConfig is used to hold whatever CPU template is stored, in whatever way. However, we can handle this at the serde layer, by making serialize/deserialize ignore the field if it doesnt contain a static template. This is ugly, but since static templates are deprecated, we have line of sight to getting rid of this weirdness when we release 2.0. While we're at it, opportunistically rename functions etc to uniformly call this thing a "machine config" instead of a "vm config". Signed-off-by: Patrick Roy --- src/cpu-template-helper/src/main.rs | 2 +- .../src/api_server/parsed_request.rs | 4 +- .../request/machine_configuration.rs | 16 +- src/vmm/benches/memory_access.rs | 6 +- src/vmm/src/builder.rs | 29 +-- src/vmm/src/persist.rs | 18 +- src/vmm/src/resources.rs | 105 ++++++----- src/vmm/src/rpc_interface.rs | 33 ++-- src/vmm/src/test_utils/mock_resources/mod.rs | 4 +- src/vmm/src/vmm_config/machine_config.rs | 176 ++++++++++++------ src/vmm/tests/integration_tests.rs | 7 +- 11 files changed, 234 insertions(+), 166 deletions(-) diff --git a/src/cpu-template-helper/src/main.rs b/src/cpu-template-helper/src/main.rs index 84a127e353a..35b7ea22d82 100644 --- a/src/cpu-template-helper/src/main.rs +++ b/src/cpu-template-helper/src/main.rs @@ -161,7 +161,7 @@ fn run(cli: Cli) -> Result<(), HelperError> { let (vmm, vm_resources) = utils::build_microvm_from_config(config, template)?; let cpu_template = vm_resources - .vm_config + .machine_config .cpu_template .get_cpu_template()? .into_owned(); diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs index 10405c156ec..41d625e9abe 100644 --- a/src/firecracker/src/api_server/parsed_request.rs +++ b/src/firecracker/src/api_server/parsed_request.rs @@ -163,8 +163,8 @@ impl ParsedRequest { info!("The request was executed successfully. Status code: 204 No Content."); Response::new(Version::Http11, StatusCode::NoContent) } - VmmData::MachineConfiguration(vm_config) => { - Self::success_response_with_data(vm_config) + VmmData::MachineConfiguration(machine_config) => { + Self::success_response_with_data(machine_config) } VmmData::MmdsValue(value) => Self::success_response_with_mmds_value(value), VmmData::BalloonConfig(balloon_config) => { diff --git a/src/firecracker/src/api_server/request/machine_configuration.rs b/src/firecracker/src/api_server/request/machine_configuration.rs index 871bbda5ecc..2409aa06cac 100644 --- a/src/firecracker/src/api_server/request/machine_configuration.rs +++ b/src/firecracker/src/api_server/request/machine_configuration.rs @@ -31,7 +31,8 @@ pub(crate) fn parse_put_machine_config(body: &Body) -> Result Result Result pub fn configure_system_for_boot( vmm: &mut Vmm, vcpus: &mut [Vcpu], - vm_config: &VmConfig, + machine_config: &MachineConfig, cpu_template: &CustomCpuTemplate, entry_addr: GuestAddress, initrd: &Option, @@ -793,8 +796,8 @@ pub fn configure_system_for_boot( let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template)?; let vcpu_config = VcpuConfig { - vcpu_count: vm_config.vcpu_count, - smt: vm_config.smt, + vcpu_count: machine_config.vcpu_count, + smt: machine_config.smt, cpu_config, }; diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 1feef41ec30..621d95d1e87 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -32,7 +32,7 @@ use crate::snapshot::Snapshot; use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootSourceConfig; use crate::vmm_config::instance_info::InstanceInfo; -use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigUpdate, VmConfigError}; +use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigError, MachineConfigUpdate}; use crate::vmm_config::snapshot::{ CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType, }; @@ -61,11 +61,11 @@ pub struct VmInfo { impl From<&VmResources> for VmInfo { fn from(value: &VmResources) -> Self { Self { - mem_size_mib: value.vm_config.mem_size_mib as u64, - smt: value.vm_config.smt, - cpu_template: StaticCpuTemplate::from(&value.vm_config.cpu_template), + mem_size_mib: value.machine_config.mem_size_mib as u64, + smt: value.machine_config.smt, + cpu_template: StaticCpuTemplate::from(&value.machine_config.cpu_template), boot_source: value.boot_source.config.clone(), - huge_pages: value.vm_config.huge_pages, + huge_pages: value.machine_config.huge_pages, } } } @@ -422,11 +422,11 @@ pub fn restore_from_snapshot( .vcpu_states .len() .try_into() - .map_err(|_| VmConfigError::InvalidVcpuCount) + .map_err(|_| MachineConfigError::InvalidVcpuCount) .map_err(BuildMicrovmFromSnapshotError::VmUpdateConfig)?; vm_resources - .update_vm_config(&MachineConfigUpdate { + .update_machine_config(&MachineConfigUpdate { vcpu_count: Some(vcpu_count), mem_size_mib: Some(u64_to_usize(microvm_state.vm_info.mem_size_mib)), smt: Some(microvm_state.vm_info.smt), @@ -450,7 +450,7 @@ pub fn restore_from_snapshot( mem_backend_path, mem_state, track_dirty_pages, - vm_resources.vm_config.huge_pages, + vm_resources.machine_config.huge_pages, ) .map_err(RestoreFromSnapshotGuestMemoryError::File)?, None, @@ -462,7 +462,7 @@ pub fn restore_from_snapshot( // We enable the UFFD_FEATURE_EVENT_REMOVE feature only if a balloon device // is present in the microVM state. microvm_state.device_states.balloon_device.is_some(), - vm_resources.vm_config.huge_pages, + vm_resources.machine_config.huge_pages, ) .map_err(RestoreFromSnapshotGuestMemoryError::Uffd)?, }; diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 0cde08a844d..d0c80789681 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -22,7 +22,7 @@ use crate::vmm_config::drive::*; use crate::vmm_config::entropy::*; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{ - HugePageConfig, MachineConfig, MachineConfigUpdate, VmConfig, VmConfigError, + HugePageConfig, MachineConfig, MachineConfigError, MachineConfigUpdate, }; use crate::vmm_config::metrics::{init_metrics, MetricsConfig, MetricsConfigError}; use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; @@ -54,7 +54,7 @@ pub enum ResourcesError { /// Network device error: {0} NetDevice(#[from] NetworkInterfaceError), /// VM config error: {0} - VmConfig(#[from] VmConfigError), + MachineConfig(#[from] MachineConfigError), /// Vsock device error: {0} VsockDevice(#[from] VsockConfigError), /// Entropy device error: {0} @@ -93,7 +93,7 @@ pub struct VmmConfig { #[derive(Debug, Default)] pub struct VmResources { /// The vCpu and memory configuration for this microVM. - pub vm_config: VmConfig, + pub machine_config: MachineConfig, /// The boot source spec (contains both config and builder) for this microVM. pub boot_source: BootSource, /// The block devices. @@ -140,7 +140,7 @@ impl VmResources { }; if let Some(machine_config) = vmm_config.machine_config { let machine_config = MachineConfigUpdate::from(machine_config); - resources.update_vm_config(&machine_config)?; + resources.update_machine_config(&machine_config)?; } if let Some(cpu_config) = vmm_config.cpu_config { @@ -219,7 +219,7 @@ impl VmResources { SharedDeviceType::Balloon(balloon) => { self.balloon.set_device(balloon); - if self.vm_config.huge_pages != HugePageConfig::None { + if self.machine_config.huge_pages != HugePageConfig::None { return Err(ResourcesError::BalloonDevice(BalloonConfigError::HugePages)); } } @@ -238,16 +238,19 @@ impl VmResources { /// Add a custom CPU template to the VM resources /// to configure vCPUs. pub fn set_custom_cpu_template(&mut self, cpu_template: CustomCpuTemplate) { - self.vm_config.set_custom_cpu_template(cpu_template); + self.machine_config.set_custom_cpu_template(cpu_template); } /// Updates the configuration of the microVM. - pub fn update_vm_config(&mut self, update: &MachineConfigUpdate) -> Result<(), VmConfigError> { + pub fn update_machine_config( + &mut self, + update: &MachineConfigUpdate, + ) -> Result<(), MachineConfigError> { if update.huge_pages.is_some() && update.huge_pages != Some(HugePageConfig::None) { log_dev_preview_warning("Huge pages support", None); } - let updated = self.vm_config.update(update)?; + let updated = self.machine_config.update(update)?; // The VM cannot have a memory size smaller than the target size // of the balloon device, if present. @@ -256,23 +259,23 @@ impl VmResources { < self .balloon .get_config() - .map_err(|_| VmConfigError::InvalidVmState)? + .map_err(|_| MachineConfigError::InvalidVmState)? .amount_mib as usize { - return Err(VmConfigError::IncompatibleBalloonSize); + return Err(MachineConfigError::IncompatibleBalloonSize); } if self.balloon.get().is_some() && updated.huge_pages != HugePageConfig::None { - return Err(VmConfigError::BalloonAndHugePages); + return Err(MachineConfigError::BalloonAndHugePages); } if self.boot_source.config.initrd_path.is_some() && updated.huge_pages != HugePageConfig::None { - return Err(VmConfigError::InitrdAndHugePages); + return Err(MachineConfigError::InitrdAndHugePages); } - self.vm_config = updated; + self.machine_config = updated; Ok(()) } @@ -322,11 +325,11 @@ impl VmResources { ) -> Result<(), BalloonConfigError> { // The balloon cannot have a target size greater than the size of // the guest memory. - if config.amount_mib as usize > self.vm_config.mem_size_mib { + if config.amount_mib as usize > self.machine_config.mem_size_mib { return Err(BalloonConfigError::TooManyPagesRequested); } - if self.vm_config.huge_pages != HugePageConfig::None { + if self.machine_config.huge_pages != HugePageConfig::None { return Err(BalloonConfigError::HugePages); } @@ -339,7 +342,7 @@ impl VmResources { boot_source_cfg: BootSourceConfig, ) -> Result<(), BootSourceConfigError> { if boot_source_cfg.initrd_path.is_some() - && self.vm_config.huge_pages != HugePageConfig::None + && self.machine_config.huge_pages != HugePageConfig::None { return Err(BootSourceConfigError::HugePagesAndInitRd); } @@ -480,16 +483,16 @@ impl VmResources { // that would not be worth the effort. if vhost_user_device_used { GuestMemoryMmap::memfd_backed( - self.vm_config.mem_size_mib, - self.vm_config.track_dirty_pages, - self.vm_config.huge_pages, + self.machine_config.mem_size_mib, + self.machine_config.track_dirty_pages, + self.machine_config.huge_pages, ) } else { - let regions = crate::arch::arch_memory_regions(self.vm_config.mem_size_mib << 20); + let regions = crate::arch::arch_memory_regions(self.machine_config.mem_size_mib << 20); GuestMemoryMmap::from_raw_regions( ®ions, - self.vm_config.track_dirty_pages, - self.vm_config.huge_pages, + self.machine_config.track_dirty_pages, + self.machine_config.huge_pages, ) } } @@ -503,7 +506,7 @@ impl From<&VmResources> for VmmConfig { boot_source: resources.boot_source.config.clone(), cpu_config: None, logger: None, - machine_config: Some(MachineConfig::from(&resources.vm_config)), + machine_config: Some(resources.machine_config.clone()), metrics: None, mmds_config: resources.mmds_config(), net_devices: resources.net_builder.configs(), @@ -535,7 +538,7 @@ mod tests { BootConfig, BootSource, BootSourceConfig, DEFAULT_KERNEL_CMDLINE, }; use crate::vmm_config::drive::{BlockBuilder, BlockDeviceConfig}; - use crate::vmm_config::machine_config::{HugePageConfig, MachineConfig, VmConfigError}; + use crate::vmm_config::machine_config::{HugePageConfig, MachineConfig, MachineConfigError}; use crate::vmm_config::net::{NetBuilder, NetworkInterfaceConfig}; use crate::vmm_config::vsock::tests::default_config; use crate::vmm_config::RateLimiterConfig; @@ -608,7 +611,7 @@ mod tests { fn default_vm_resources() -> VmResources { VmResources { - vm_config: VmConfig::default(), + machine_config: MachineConfig::default(), boot_source: default_boot_cfg(), block: default_blocks(), vsock: Default::default(), @@ -821,7 +824,7 @@ mod tests { assert!( matches!( error, - ResourcesError::VmConfig(VmConfigError::InvalidMemorySize) + ResourcesError::MachineConfig(MachineConfigError::InvalidMemorySize) ), "{:?}", error @@ -1135,7 +1138,7 @@ mod tests { ) .unwrap(); assert_eq!( - vm_resources.vm_config.cpu_template, + vm_resources.machine_config.cpu_template, Some(CpuTemplateType::Custom(CustomCpuTemplate::default())) ); } @@ -1339,7 +1342,7 @@ mod tests { } #[test] - fn test_update_vm_config() { + fn test_update_machine_config() { let mut vm_resources = default_vm_resources(); let mut aux_vm_config = MachineConfigUpdate { vcpu_count: Some(32), @@ -1354,25 +1357,25 @@ mod tests { }; assert_ne!( - MachineConfigUpdate::from(MachineConfig::from(&vm_resources.vm_config)), + MachineConfigUpdate::from(vm_resources.machine_config.clone()), aux_vm_config ); - vm_resources.update_vm_config(&aux_vm_config).unwrap(); + vm_resources.update_machine_config(&aux_vm_config).unwrap(); assert_eq!( - MachineConfigUpdate::from(MachineConfig::from(&vm_resources.vm_config)), + MachineConfigUpdate::from(vm_resources.machine_config.clone()), aux_vm_config ); // Invalid vcpu count. aux_vm_config.vcpu_count = Some(0); assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::InvalidVcpuCount) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::InvalidVcpuCount) ); aux_vm_config.vcpu_count = Some(33); assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::InvalidVcpuCount) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::InvalidVcpuCount) ); // Check that SMT is not supported on aarch64, and that on x86_64 enabling it requires vcpu @@ -1380,29 +1383,29 @@ mod tests { aux_vm_config.smt = Some(true); #[cfg(target_arch = "aarch64")] assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::SmtNotSupported) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::SmtNotSupported) ); aux_vm_config.vcpu_count = Some(3); #[cfg(target_arch = "x86_64")] assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::InvalidVcpuCount) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::InvalidVcpuCount) ); aux_vm_config.vcpu_count = Some(32); #[cfg(target_arch = "x86_64")] - vm_resources.update_vm_config(&aux_vm_config).unwrap(); + vm_resources.update_machine_config(&aux_vm_config).unwrap(); aux_vm_config.smt = Some(false); // Invalid mem_size_mib. aux_vm_config.mem_size_mib = Some(0); assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::InvalidMemorySize) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::InvalidMemorySize) ); // Incompatible mem_size_mib with balloon size. - vm_resources.vm_config.mem_size_mib = 128; + vm_resources.machine_config.mem_size_mib = 128; vm_resources .set_balloon_device(BalloonDeviceConfig { amount_mib: 100, @@ -1412,20 +1415,22 @@ mod tests { .unwrap(); aux_vm_config.mem_size_mib = Some(90); assert_eq!( - vm_resources.update_vm_config(&aux_vm_config), - Err(VmConfigError::IncompatibleBalloonSize) + vm_resources.update_machine_config(&aux_vm_config), + Err(MachineConfigError::IncompatibleBalloonSize) ); // mem_size_mib compatible with balloon size. aux_vm_config.mem_size_mib = Some(256); - vm_resources.update_vm_config(&aux_vm_config).unwrap(); + vm_resources.update_machine_config(&aux_vm_config).unwrap(); // mem_size_mib incompatible with huge pages configuration aux_vm_config.mem_size_mib = Some(129); aux_vm_config.huge_pages = Some(HugePageConfig::Hugetlbfs2M); assert_eq!( - vm_resources.update_vm_config(&aux_vm_config).unwrap_err(), - VmConfigError::InvalidMemorySize + vm_resources + .update_machine_config(&aux_vm_config) + .unwrap_err(), + MachineConfigError::InvalidMemorySize ); // mem_size_mib compatible with huge page configuration @@ -1433,7 +1438,7 @@ mod tests { // Remove the balloon device config that's added by `default_vm_resources` as it would // trigger the "ballooning incompatible with huge pages" check. vm_resources.balloon = BalloonBuilder::new(); - vm_resources.update_vm_config(&aux_vm_config).unwrap(); + vm_resources.update_machine_config(&aux_vm_config).unwrap(); } #[test] @@ -1474,7 +1479,7 @@ mod tests { let mut vm_resources = default_vm_resources(); vm_resources.balloon = BalloonBuilder::new(); vm_resources - .update_vm_config(&MachineConfigUpdate { + .update_machine_config(&MachineConfigUpdate { huge_pages: Some(HugePageConfig::Hugetlbfs2M), ..Default::default() }) diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 60a046f7e89..82993fcafea 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -26,7 +26,7 @@ use crate::vmm_config::boot_source::{BootSourceConfig, BootSourceConfigError}; use crate::vmm_config::drive::{BlockDeviceConfig, BlockDeviceUpdateConfig, DriveError}; use crate::vmm_config::entropy::{EntropyDeviceConfig, EntropyDeviceError}; use crate::vmm_config::instance_info::InstanceInfo; -use crate::vmm_config::machine_config::{MachineConfig, MachineConfigUpdate, VmConfigError}; +use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError, MachineConfigUpdate}; use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError}; use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; use crate::vmm_config::net::{ @@ -120,7 +120,7 @@ pub enum VmmAction { UpdateNetworkInterface(NetworkInterfaceUpdateConfig), /// Update the microVM configuration (memory & vcpu) using `VmUpdateConfig` as input. This /// action can only be called before the microVM has booted. - UpdateVmConfiguration(MachineConfigUpdate), + UpdateMachineConfiguration(MachineConfigUpdate), } /// Wrapper for all errors associated with VMM actions. @@ -145,7 +145,7 @@ pub enum VmmActionError { /// Logger error: {0} Logger(#[from] crate::logger::LoggerUpdateError), /// Machine config error: {0} - MachineConfig(#[from] VmConfigError), + MachineConfig(#[from] MachineConfigError), /// Metrics error: {0} Metrics(#[from] MetricsConfigError), #[from(ignore)] @@ -415,9 +415,9 @@ impl<'a> PrebootApiController<'a> { Ok(VmmData::FullVmConfig((&*self.vm_resources).into())) } GetMMDS => self.get_mmds(), - GetVmMachineConfig => Ok(VmmData::MachineConfiguration(MachineConfig::from( - &self.vm_resources.vm_config, - ))), + GetVmMachineConfig => Ok(VmmData::MachineConfiguration( + self.vm_resources.machine_config.clone(), + )), GetVmInstanceInfo => Ok(VmmData::InstanceInformation(self.instance_info.clone())), GetVmmVersion => Ok(VmmData::VmmVersion(self.instance_info.vmm_version.clone())), InsertBlockDevice(config) => self.insert_block_device(config), @@ -434,7 +434,7 @@ impl<'a> PrebootApiController<'a> { SetVsockDevice(config) => self.set_vsock_device(config), SetMmdsConfiguration(config) => self.set_mmds_config(config), StartMicroVm => self.start_microvm(), - UpdateVmConfiguration(config) => self.update_vm_config(config), + UpdateMachineConfiguration(config) => self.update_machine_config(config), SetEntropyDevice(config) => self.set_entropy_device(config), // Operations not allowed pre-boot. CreateSnapshot(_) @@ -502,10 +502,13 @@ impl<'a> PrebootApiController<'a> { .map_err(VmmActionError::MmdsConfig) } - fn update_vm_config(&mut self, cfg: MachineConfigUpdate) -> Result { + fn update_machine_config( + &mut self, + cfg: MachineConfigUpdate, + ) -> Result { self.boot_path = true; self.vm_resources - .update_vm_config(&cfg) + .update_machine_config(&cfg) .map(|()| VmmData::Empty) .map_err(VmmActionError::MachineConfig) } @@ -641,9 +644,9 @@ impl RuntimeApiController { .map_err(|err| VmmActionError::BalloonConfig(BalloonConfigError::from(err))), GetFullVmConfig => Ok(VmmData::FullVmConfig((&self.vm_resources).into())), GetMMDS => self.get_mmds(), - GetVmMachineConfig => Ok(VmmData::MachineConfiguration(MachineConfig::from( - &self.vm_resources.vm_config, - ))), + GetVmMachineConfig => Ok(VmmData::MachineConfiguration( + self.vm_resources.machine_config.clone(), + )), GetVmInstanceInfo => Ok(VmmData::InstanceInformation( self.vmm.lock().expect("Poisoned lock").instance_info(), )), @@ -686,7 +689,7 @@ impl RuntimeApiController { | SetMmdsConfiguration(_) | SetEntropyDevice(_) | StartMicroVm - | UpdateVmConfiguration(_) => Err(VmmActionError::OperationNotSupportedPostBoot), + | UpdateMachineConfiguration(_) => Err(VmmActionError::OperationNotSupportedPostBoot), } } @@ -753,7 +756,7 @@ impl RuntimeApiController { log_dev_preview_warning("Virtual machine snapshots", None); if create_params.snapshot_type == SnapshotType::Diff - && !self.vm_resources.vm_config.track_dirty_pages + && !self.vm_resources.machine_config.track_dirty_pages { return Err(VmmActionError::NotSupported( "Diff snapshots are not allowed on uVMs with dirty page tracking disabled." @@ -1254,7 +1257,7 @@ mod tests { network_interfaces: Vec::new(), }, ))); - check_unsupported(runtime_request(VmmAction::UpdateVmConfiguration( + check_unsupported(runtime_request(VmmAction::UpdateMachineConfiguration( MachineConfigUpdate::from(MachineConfig::default()), ))); check_unsupported(runtime_request(VmmAction::LoadSnapshot( diff --git a/src/vmm/src/test_utils/mock_resources/mod.rs b/src/vmm/src/test_utils/mock_resources/mod.rs index 9f4406ab280..f8485bf9678 100644 --- a/src/vmm/src/test_utils/mock_resources/mod.rs +++ b/src/vmm/src/test_utils/mock_resources/mod.rs @@ -81,12 +81,12 @@ impl MockVmResources { pub fn with_vm_config(mut self, vm_config: MachineConfig) -> Self { let machine_config = MachineConfigUpdate::from(vm_config); - self.0.update_vm_config(&machine_config).unwrap(); + self.0.update_machine_config(&machine_config).unwrap(); self } pub fn set_cpu_template(&mut self, cpu_template: CustomCpuTemplate) { - self.0.vm_config.set_custom_cpu_template(cpu_template); + self.0.machine_config.set_custom_cpu_template(cpu_template); } } diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 482fcfdd08f..092179f5ff5 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use std::fmt::Debug; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::cpu_config::templates::{CpuTemplateType, CustomCpuTemplate, StaticCpuTemplate}; @@ -15,7 +15,7 @@ pub const MAX_SUPPORTED_VCPUS: u8 = 32; /// Errors associated with configuring the microVM. #[rustfmt::skip] #[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)] -pub enum VmConfigError { +pub enum MachineConfigError { /// The memory size (MiB) is smaller than the previously set balloon device target size. IncompatibleBalloonSize, /// The memory size (MiB) is either 0, or not a multiple of the configured page size. @@ -103,8 +103,14 @@ pub struct MachineConfig { #[serde(default)] pub smt: bool, /// A CPU template that it is used to filter the CPU features exposed to the guest. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub cpu_template: Option, + // FIXME: once support for static CPU templates is removed, this field can be dropped altogether + #[serde( + default, + skip_serializing_if = "is_none_or_custom_template", + deserialize_with = "deserialize_static_template", + serialize_with = "serialize_static_template" + )] + pub cpu_template: Option, /// Enables or disables dirty page tracking. Enabling allows incremental snapshots. #[serde(default)] pub track_dirty_pages: bool, @@ -117,14 +123,50 @@ pub struct MachineConfig { pub gdb_socket_path: Option, } +fn is_none_or_custom_template(template: &Option) -> bool { + matches!(template, None | Some(CpuTemplateType::Custom(_))) +} + +fn deserialize_static_template<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + Option::::deserialize(deserializer) + .map(|maybe_template| maybe_template.map(CpuTemplateType::Static)) +} + +fn serialize_static_template( + template: &Option, + serializer: S, +) -> Result +where + S: Serializer, +{ + let Some(CpuTemplateType::Static(template)) = template else { + // We have a skip_serializing_if on the field + unreachable!() + }; + + template.serialize(serializer) +} + impl Default for MachineConfig { fn default() -> Self { - Self::from(&VmConfig::default()) + Self { + vcpu_count: 1, + mem_size_mib: DEFAULT_MEM_SIZE_MIB, + smt: false, + cpu_template: None, + track_dirty_pages: false, + huge_pages: HugePageConfig::None, + #[cfg(feature = "gdb")] + gdb_socket_path: None, + } } } /// Struct used in PATCH `/machine-config` API call. -/// Used to update `VmConfig` in `VmResources`. +/// Used to update `MachineConfig` in `VmResources`. /// This struct mirrors all the fields in `MachineConfig`. /// All fields are optional, but at least one needs to be specified. /// If a field is `Some(value)` then we assume an update is requested @@ -171,7 +213,7 @@ impl From for MachineConfigUpdate { vcpu_count: Some(cfg.vcpu_count), mem_size_mib: Some(cfg.mem_size_mib), smt: Some(cfg.smt), - cpu_template: cfg.cpu_template, + cpu_template: cfg.static_template(), track_dirty_pages: Some(cfg.track_dirty_pages), huge_pages: Some(cfg.huge_pages), #[cfg(feature = "gdb")] @@ -180,62 +222,52 @@ impl From for MachineConfigUpdate { } } -/// Configuration of the microvm. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct VmConfig { - /// Number of vcpu to start. - pub vcpu_count: u8, - /// The memory size in MiB. - pub mem_size_mib: usize, - /// Enables or disabled SMT. - pub smt: bool, - /// A CPU template that it is used to filter the CPU features exposed to the guest. - pub cpu_template: Option, - /// Enables or disables dirty page tracking. Enabling allows incremental snapshots. - pub track_dirty_pages: bool, - /// Configures what page size Firecracker should use to back guest memory. - pub huge_pages: HugePageConfig, - /// GDB socket address. - #[cfg(feature = "gdb")] - pub gdb_socket_path: Option, -} - -impl VmConfig { +impl MachineConfig { /// Sets cpu tempalte field to `CpuTemplateType::Custom(cpu_template)`. pub fn set_custom_cpu_template(&mut self, cpu_template: CustomCpuTemplate) { self.cpu_template = Some(CpuTemplateType::Custom(cpu_template)); } - /// Updates [`VmConfig`] with [`MachineConfigUpdate`]. + fn static_template(&self) -> Option { + match self.cpu_template { + Some(CpuTemplateType::Static(template)) => Some(template), + _ => None, + } + } + + /// Updates [`MachineConfig`] with [`MachineConfigUpdate`]. /// Mapping for cpu template update: /// StaticCpuTemplate::None -> None /// StaticCpuTemplate::Other -> Some(CustomCpuTemplate::Static(Other)), - /// Returns the updated `VmConfig` object. - pub fn update(&self, update: &MachineConfigUpdate) -> Result { + /// Returns the updated `MachineConfig` object. + pub fn update( + &self, + update: &MachineConfigUpdate, + ) -> Result { let vcpu_count = update.vcpu_count.unwrap_or(self.vcpu_count); let smt = update.smt.unwrap_or(self.smt); #[cfg(target_arch = "aarch64")] if smt { - return Err(VmConfigError::SmtNotSupported); + return Err(MachineConfigError::SmtNotSupported); } if vcpu_count == 0 || vcpu_count > MAX_SUPPORTED_VCPUS { - return Err(VmConfigError::InvalidVcpuCount); + return Err(MachineConfigError::InvalidVcpuCount); } // If SMT is enabled or is to be enabled in this call // only allow vcpu count to be 1 or even. if smt && vcpu_count > 1 && vcpu_count % 2 == 1 { - return Err(VmConfigError::InvalidVcpuCount); + return Err(MachineConfigError::InvalidVcpuCount); } let mem_size_mib = update.mem_size_mib.unwrap_or(self.mem_size_mib); let page_config = update.huge_pages.unwrap_or(self.huge_pages); if mem_size_mib == 0 || !page_config.is_valid_mem_size(mem_size_mib) { - return Err(VmConfigError::InvalidMemorySize); + return Err(MachineConfigError::InvalidMemorySize); } let cpu_template = match update.cpu_template { @@ -244,7 +276,7 @@ impl VmConfig { Some(other) => Some(CpuTemplateType::Static(other)), }; - Ok(VmConfig { + Ok(MachineConfig { vcpu_count, mem_size_mib, smt, @@ -257,32 +289,54 @@ impl VmConfig { } } -impl Default for VmConfig { - fn default() -> Self { - Self { - vcpu_count: 1, - mem_size_mib: DEFAULT_MEM_SIZE_MIB, - smt: false, +#[cfg(test)] +mod tests { + use crate::cpu_config::templates::{CpuTemplateType, CustomCpuTemplate, StaticCpuTemplate}; + use crate::vmm_config::machine_config::MachineConfig; + + // Ensure the special (de)serialization logic for the cpu_template field works: + // only static cpu templates can be specified via the machine-config endpoint, but + // we still cram custom cpu templates into the MachineConfig struct if they're set otherwise + // Ensure that during (de)serialization we preserve static templates, but we set custom + // templates to None + #[test] + fn test_serialize_machine_config() { + #[cfg(target_arch = "aarch64")] + const TEMPLATE: StaticCpuTemplate = StaticCpuTemplate::V1N1; + #[cfg(target_arch = "x86_64")] + const TEMPLATE: StaticCpuTemplate = StaticCpuTemplate::T2S; + + let mconfig = MachineConfig { cpu_template: None, - track_dirty_pages: false, - huge_pages: HugePageConfig::None, - #[cfg(feature = "gdb")] - gdb_socket_path: None, - } - } -} + ..Default::default() + }; -impl From<&VmConfig> for MachineConfig { - fn from(value: &VmConfig) -> Self { - Self { - vcpu_count: value.vcpu_count, - mem_size_mib: value.mem_size_mib, - smt: value.smt, - cpu_template: value.cpu_template.as_ref().map(|template| template.into()), - track_dirty_pages: value.track_dirty_pages, - huge_pages: value.huge_pages, - #[cfg(feature = "gdb")] - gdb_socket_path: value.gdb_socket_path.clone(), - } + let serialized = serde_json::to_string(&mconfig).unwrap(); + let deserialized = serde_json::from_str::(&serialized).unwrap(); + + assert!(deserialized.cpu_template.is_none()); + + let mconfig = MachineConfig { + cpu_template: Some(CpuTemplateType::Static(TEMPLATE)), + ..Default::default() + }; + + let serialized = serde_json::to_string(&mconfig).unwrap(); + let deserialized = serde_json::from_str::(&serialized).unwrap(); + + assert_eq!( + deserialized.cpu_template, + Some(CpuTemplateType::Static(TEMPLATE)) + ); + + let mconfig = MachineConfig { + cpu_template: Some(CpuTemplateType::Custom(CustomCpuTemplate::default())), + ..Default::default() + }; + + let serialized = serde_json::to_string(&mconfig).unwrap(); + let deserialized = serde_json::from_str::(&serialized).unwrap(); + + assert!(deserialized.cpu_template.is_none()); } } diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index 40eab05c4a4..a66f29e7f55 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -22,7 +22,7 @@ use vmm::vmm_config::balloon::BalloonDeviceConfig; use vmm::vmm_config::boot_source::BootSourceConfig; use vmm::vmm_config::drive::BlockDeviceConfig; use vmm::vmm_config::instance_info::{InstanceInfo, VmState}; -use vmm::vmm_config::machine_config::{MachineConfig, MachineConfigUpdate, VmConfig}; +use vmm::vmm_config::machine_config::{MachineConfig, MachineConfigUpdate}; use vmm::vmm_config::net::NetworkInterfaceConfig; use vmm::vmm_config::snapshot::{ CreateSnapshotParams, LoadSnapshotParams, MemBackendConfig, MemBackendType, SnapshotType, @@ -188,7 +188,7 @@ fn verify_create_snapshot(is_diff: bool) -> (TempFile, TempFile) { let (vmm, _) = create_vmm(Some(NOISY_KERNEL_IMAGE), is_diff, true); let resources = VmResources { - vm_config: VmConfig { + machine_config: MachineConfig { mem_size_mib: 1, track_dirty_pages: is_diff, ..Default::default() @@ -403,6 +403,7 @@ fn test_preboot_load_snap_disallowed_after_boot_resources() { }); verify_load_snap_disallowed_after_boot_resources(req, "SetVsockDevice"); - let req = VmmAction::UpdateVmConfiguration(MachineConfigUpdate::from(MachineConfig::default())); + let req = + VmmAction::UpdateMachineConfiguration(MachineConfigUpdate::from(MachineConfig::default())); verify_load_snap_disallowed_after_boot_resources(req, "SetVmConfiguration"); } From 9e011ba19d0f1c4e0e646888f0b1ce3a41c689fe Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 10 Jan 2025 14:22:37 +0000 Subject: [PATCH 168/464] examples: Have UFFD handler kill Firecracker should it die If the UFFD handler exits abnormaly for some reason, have it take down Firecracker as well by SIGKILL-ing it from a panic hook. For this, reintroduce the "get peer creds" logic. We have to use SIGKILL because Firecracker could be inside the handler for a KVM-originated page fault that is not marked as interruptible, in which case all signals but SIGKILL are ignored (happens for example during KVM_SET_MSRS when it triggers the initialization of a gfn_to_pfn_cache for the kvm-clock page, which uses GUP without FOLL_INTERRUPTIBLE). While we're at it, add a hint to the generic "process not found" error message to indicate that potentially Firecracker died, and that the cause of this could be the UFFD handler crashing (for example, in #4601 the cause of the mystery hang is the UFFD handler crashing, but we were stumped by what's going on for over half a year. Let's avoid that going forward). We can't enable this by default because it interferes with unittests, and also the "malicious_handler", so expose a function on `Runtime` to enable it only in valid_handler and fault_all_handler. Signed-off-by: Patrick Roy --- .../examples/uffd/fault_all_handler.rs | 1 + src/firecracker/examples/uffd/uffd_utils.rs | 37 +++++++++++++++++++ .../examples/uffd/valid_handler.rs | 1 + tests/framework/microvm.py | 3 ++ 4 files changed, 42 insertions(+) diff --git a/src/firecracker/examples/uffd/fault_all_handler.rs b/src/firecracker/examples/uffd/fault_all_handler.rs index 31ce68a97bc..5e9f49a3207 100644 --- a/src/firecracker/examples/uffd/fault_all_handler.rs +++ b/src/firecracker/examples/uffd/fault_all_handler.rs @@ -24,6 +24,7 @@ fn main() { let (stream, _) = listener.accept().expect("Cannot listen on UDS socket"); let mut runtime = Runtime::new(stream, file); + runtime.install_panic_hook(); runtime.run(|uffd_handler: &mut UffdHandler| { // Read an event from the userfaultfd. let event = uffd_handler diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index 52d33765bd8..37aa63c62a3 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -208,6 +208,43 @@ impl Runtime { } } + fn peer_process_credentials(&self) -> libc::ucred { + let mut creds: libc::ucred = libc::ucred { + pid: 0, + gid: 0, + uid: 0, + }; + let mut creds_size = size_of::() as u32; + let ret = unsafe { + libc::getsockopt( + self.stream.as_raw_fd(), + libc::SOL_SOCKET, + libc::SO_PEERCRED, + &mut creds as *mut _ as *mut _, + &mut creds_size as *mut libc::socklen_t, + ) + }; + if ret != 0 { + panic!("Failed to get peer process credentials"); + } + creds + } + + pub fn install_panic_hook(&self) { + let peer_creds = self.peer_process_credentials(); + + let default_panic_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |panic_info| { + let r = unsafe { libc::kill(peer_creds.pid, libc::SIGKILL) }; + + if r != 0 { + eprintln!("Failed to kill Firecracker process from panic hook"); + } + + default_panic_hook(panic_info); + })); + } + /// Polls the `UnixStream` and UFFD fds in a loop. /// When stream is polled, new uffd is retrieved. /// When uffd is polled, page fault is handled by diff --git a/src/firecracker/examples/uffd/valid_handler.rs b/src/firecracker/examples/uffd/valid_handler.rs index cfc5faf432c..6c681d932ac 100644 --- a/src/firecracker/examples/uffd/valid_handler.rs +++ b/src/firecracker/examples/uffd/valid_handler.rs @@ -24,6 +24,7 @@ fn main() { let (stream, _) = listener.accept().expect("Cannot listen on UDS socket"); let mut runtime = Runtime::new(stream, file); + runtime.install_panic_hook(); runtime.run(|uffd_handler: &mut UffdHandler| { // Read an event from the userfaultfd. let event = uffd_handler diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 278cb9ecd60..f93a0dabf19 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -310,6 +310,9 @@ def kill(self): if self.screen_pid: os.kill(self.screen_pid, signal.SIGKILL) except: + LOG.error( + "Failed to kill Firecracker Process. Did it already die (or did the UFFD handler process die and take it down)?" + ) LOG.error(self.log_data) raise From 3fb06e940d8ad0508c31984cf0f8cb947282430b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 10 Jan 2025 09:57:08 +0000 Subject: [PATCH 169/464] fix: avoid needless clone in build_microvm_from_snapshot There is no need to clone the GuestMemoryMmap here, as create_vmm_and_vcpus returns it again (as part of the Vmm object), and since later code in build_microvm_from_snapshot doesn't need to take ownership of the GuestMemoryMmap, we can just use references to this stored object, avoiding the clone. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 433d1fd4ff3..999e27415fc 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -472,7 +472,7 @@ pub fn build_microvm_from_snapshot( let (mut vmm, mut vcpus) = create_vmm_and_vcpus( instance_info, event_manager, - guest_memory.clone(), + guest_memory, uffd, vm_resources.machine_config.track_dirty_pages, vm_resources.machine_config.vcpu_count, @@ -517,7 +517,7 @@ pub fn build_microvm_from_snapshot( // Restore devices states. let mmio_ctor_args = MMIODevManagerConstructorArgs { - mem: &guest_memory, + mem: &vmm.guest_memory, vm: vmm.vm.fd(), event_manager, resource_allocator: &mut vmm.resource_allocator, @@ -532,7 +532,7 @@ pub fn build_microvm_from_snapshot( { let acpi_ctor_args = ACPIDeviceManagerConstructorArgs { - mem: &guest_memory, + mem: &vmm.guest_memory, resource_allocator: &mut vmm.resource_allocator, vm: vmm.vm.fd(), }; From 0efae509cc815774934e67f658bad143841f7cdd Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 14 Jan 2025 17:32:43 +0000 Subject: [PATCH 170/464] refactor: move KVM related logic into a separate struct `Vm` constructor was the only place where the `/dev/kvm` was open and only there we could do any KVM (not VM) specific checks. By moving this KVM logic into a separate struct we can can do KVM specific actions (like checking optional KVM capabilities) without needing to reopen the `/dev/kvm` again. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/vcpu.rs | 18 +-- src/vmm/src/builder.rs | 38 +++-- src/vmm/src/device_manager/legacy.rs | 7 +- src/vmm/src/device_manager/mmio.rs | 10 +- src/vmm/src/lib.rs | 6 + src/vmm/src/persist.rs | 4 + src/vmm/src/vstate/kvm.rs | 205 +++++++++++++++++++++++++++ src/vmm/src/vstate/mod.rs | 2 + src/vmm/src/vstate/vcpu/aarch64.rs | 46 +++--- src/vmm/src/vstate/vcpu/mod.rs | 34 ++--- src/vmm/src/vstate/vcpu/x86_64.rs | 77 +++++----- src/vmm/src/vstate/vm.rs | 198 ++++---------------------- 12 files changed, 372 insertions(+), 273 deletions(-) create mode 100644 src/vmm/src/vstate/kvm.rs diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 80fc5a339df..859e2da2cb6 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -214,16 +214,16 @@ pub fn set_mpstate(vcpufd: &VcpuFd, state: kvm_mp_state) -> Result<(), VcpuError #[cfg(test)] mod tests { #![allow(clippy::undocumented_unsafe_blocks)] - use kvm_ioctls::Kvm; use super::*; use crate::arch::aarch64::layout; use crate::test_utils::arch_mem; + use crate::vstate::kvm::Kvm; #[test] fn test_setup_regs() { - let kvm = Kvm::new().unwrap(); - let vm = kvm.create_vm().unwrap(); + let kvm = Kvm::new(vec![]).unwrap(); + let vm = kvm.fd.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000); @@ -242,8 +242,8 @@ mod tests { #[test] fn test_read_mpidr() { - let kvm = Kvm::new().unwrap(); - let vm = kvm.create_vm().unwrap(); + let kvm = Kvm::new(vec![]).unwrap(); + let vm = kvm.fd.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); vm.get_preferred_target(&mut kvi).unwrap(); @@ -261,8 +261,8 @@ mod tests { #[test] fn test_get_set_regs() { - let kvm = Kvm::new().unwrap(); - let vm = kvm.create_vm().unwrap(); + let kvm = Kvm::new(vec![]).unwrap(); + let vm = kvm.fd.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); vm.get_preferred_target(&mut kvi).unwrap(); @@ -283,8 +283,8 @@ mod tests { fn test_mpstate() { use std::os::unix::io::AsRawFd; - let kvm = Kvm::new().unwrap(); - let vm = kvm.create_vm().unwrap(); + let kvm = Kvm::new(vec![]).unwrap(); + let vm = kvm.fd.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); vm.get_preferred_target(&mut kvi).unwrap(); diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 999e27415fc..6a59fe35a83 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -68,6 +68,7 @@ use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootConfig; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; +use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; use crate::vstate::vm::Vm; @@ -160,11 +161,17 @@ fn create_vmm_and_vcpus( ) -> Result<(Vmm, Vec), StartMicrovmError> { use self::StartMicrovmError::*; + let kvm = Kvm::new(kvm_capabilities) + .map_err(VmmError::Kvm) + .map_err(StartMicrovmError::Internal)?; // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. - let mut vm = Vm::new(kvm_capabilities) + let mut vm = Vm::new(&kvm) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; + kvm.check_memory(&guest_memory) + .map_err(VmmError::Kvm) + .map_err(StartMicrovmError::Internal)?; vm.memory_init(&guest_memory, track_dirty_pages) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; @@ -186,7 +193,7 @@ fn create_vmm_and_vcpus( #[cfg(target_arch = "x86_64")] let (vcpus, pio_device_manager) = { setup_interrupt_controller(&mut vm)?; - let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; + let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; // Make stdout non blocking. set_stdout_nonblocking(); @@ -218,7 +225,7 @@ fn create_vmm_and_vcpus( // Search for `kvm_arch_vcpu_create` in arch/arm/kvm/arm.c. #[cfg(target_arch = "aarch64")] let vcpus = { - let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; + let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; setup_interrupt_controller(&mut vm, vcpu_count)?; vcpus }; @@ -227,6 +234,7 @@ fn create_vmm_and_vcpus( events_observer: Some(std::io::stdin()), instance_info: instance_info.clone(), shutdown_exit_code: None, + kvm, vm, guest_memory, uffd, @@ -476,7 +484,7 @@ pub fn build_microvm_from_snapshot( uffd, vm_resources.machine_config.track_dirty_pages, vm_resources.machine_config.vcpu_count, - microvm_state.vm_state.kvm_cap_modifiers.clone(), + microvm_state.kvm_state.kvm_cap_modifiers.clone(), )?; #[cfg(target_arch = "x86_64")] @@ -738,11 +746,16 @@ fn attach_legacy_devices_aarch64( .map_err(VmmError::RegisterMMIODevice) } -fn create_vcpus(vm: &Vm, vcpu_count: u8, exit_evt: &EventFd) -> Result, VmmError> { +fn create_vcpus( + kvm: &Kvm, + vm: &Vm, + vcpu_count: u8, + exit_evt: &EventFd, +) -> Result, VmmError> { let mut vcpus = Vec::with_capacity(vcpu_count as usize); for cpu_idx in 0..vcpu_count { let exit_evt = exit_evt.try_clone().map_err(VmmError::EventFd)?; - let vcpu = Vcpu::new(cpu_idx, vm, exit_evt).map_err(VmmError::VcpuCreate)?; + let vcpu = Vcpu::new(cpu_idx, vm, kvm, exit_evt).map_err(VmmError::VcpuCreate)?; vcpus.push(vcpu); } Ok(vcpus) @@ -765,7 +778,7 @@ pub fn configure_system_for_boot( #[cfg(target_arch = "x86_64")] let cpu_config = { use crate::cpu_config::x86_64::cpuid; - let cpuid = cpuid::Cpuid::try_from(vmm.vm.supported_cpuid().clone()) + let cpuid = cpuid::Cpuid::try_from(vmm.kvm.supported_cpuid.clone()) .map_err(GuestConfigError::CpuidFromKvmCpuid)?; let msrs = vcpus[0] .kvm_vcpu @@ -1111,7 +1124,8 @@ pub(crate) mod tests { .map_err(StartMicrovmError::Internal) .unwrap(); - let mut vm = Vm::new(vec![]).unwrap(); + let kvm = Kvm::new(vec![]).unwrap(); + let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_memory, false).unwrap(); let mmio_device_manager = MMIODeviceManager::new(); let acpi_device_manager = ACPIDeviceManager::new(); @@ -1137,7 +1151,7 @@ pub(crate) mod tests { #[cfg(target_arch = "aarch64")] { let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); - let _vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); + let _vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap(); setup_interrupt_controller(&mut vm, 1).unwrap(); } @@ -1145,6 +1159,7 @@ pub(crate) mod tests { events_observer: Some(std::io::stdin()), instance_info: InstanceInfo::default(), shutdown_exit_code: None, + kvm, vm, guest_memory, uffd: None, @@ -1362,15 +1377,16 @@ pub(crate) mod tests { let vcpu_count = 2; let guest_memory = arch_mem(128 << 20); + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); #[allow(unused_mut)] - let mut vm = Vm::new(vec![]).unwrap(); + let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_memory, false).unwrap(); let evfd = EventFd::new(libc::EFD_NONBLOCK).unwrap(); #[cfg(target_arch = "x86_64")] setup_interrupt_controller(&mut vm).unwrap(); - let vcpu_vec = create_vcpus(&vm, vcpu_count, &evfd).unwrap(); + let vcpu_vec = create_vcpus(&kvm, &vm, vcpu_count, &evfd).unwrap(); assert_eq!(vcpu_vec.len(), vcpu_count as usize); } diff --git a/src/vmm/src/device_manager/legacy.rs b/src/vmm/src/device_manager/legacy.rs index 45842d933b2..8526d3c2901 100644 --- a/src/vmm/src/device_manager/legacy.rs +++ b/src/vmm/src/device_manager/legacy.rs @@ -244,14 +244,11 @@ impl PortIODeviceManager { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::single_region_mem; - use crate::Vm; + use crate::vstate::vm::tests::setup_vm_with_memory; #[test] fn test_register_legacy_devices() { - let guest_mem = single_region_mem(0x1000); - let mut vm = Vm::new(vec![]).unwrap(); - vm.memory_init(&guest_mem, false).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); crate::builder::setup_interrupt_controller(&mut vm).unwrap(); let mut ldm = PortIODeviceManager::new( Arc::new(Mutex::new(BusDevice::Serial(SerialDevice { diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index 00c155abcfd..635bc1bc6e0 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -544,6 +544,7 @@ mod tests { use crate::devices::virtio::queue::Queue; use crate::devices::virtio::ActivateError; use crate::test_utils::multi_region_mem; + use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::{builder, Vm}; @@ -661,7 +662,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); - let mut vm = Vm::new(vec![]).unwrap(); + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_mem, false).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -690,7 +692,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); - let mut vm = Vm::new(vec![]).unwrap(); + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_mem, false).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -744,7 +747,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); - let mut vm = Vm::new(vec![]).unwrap(); + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_mem, false).unwrap(); let mem_clone = guest_mem.clone(); diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 77c0018c55a..6833a3a12d2 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -127,6 +127,7 @@ use userfaultfd::Uffd; use vmm_sys_util::epoll::EventSet; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::terminal::Terminal; +use vstate::kvm::Kvm; use vstate::vcpu::{self, KvmVcpuConfigureError, StartThreadedError, VcpuSendEventError}; use crate::arch::DeviceType; @@ -255,6 +256,8 @@ pub enum VmmError { VcpuSpawn(io::Error), /// Vm error: {0} Vm(vstate::vm::VmError), + /// Kvm error: {0} + Kvm(vstate::kvm::KvmError), /// Error thrown by observer object on Vmm initialization: {0} VmmObserverInit(vmm_sys_util::errno::Error), /// Error thrown by observer object on Vmm teardown: {0} @@ -307,6 +310,7 @@ pub struct Vmm { shutdown_exit_code: Option, // Guest VM core resources. + kvm: Kvm, vm: Vm, guest_memory: GuestMemoryMmap, // Save UFFD in order to keep it open in the Firecracker process, as well. @@ -511,6 +515,7 @@ impl Vmm { pub fn save_state(&mut self, vm_info: &VmInfo) -> Result { use self::MicrovmStateError::SaveVmState; let vcpu_states = self.save_vcpu_states()?; + let kvm_state = self.kvm.save_state(); let vm_state = { #[cfg(target_arch = "x86_64")] { @@ -531,6 +536,7 @@ impl Vmm { Ok(MicrovmState { vm_info: vm_info.clone(), memory_state, + kvm_state, vm_state, vcpu_states, device_states, diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 621d95d1e87..c9aadad10a9 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -36,6 +36,7 @@ use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigError, Mach use crate::vmm_config::snapshot::{ CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType, }; +use crate::vstate::kvm::KvmState; use crate::vstate::memory::{ GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryState, MemoryError, }; @@ -77,6 +78,8 @@ pub struct MicrovmState { pub vm_info: VmInfo, /// Memory state. pub memory_state: GuestMemoryState, + /// KVM KVM state. + pub kvm_state: KvmState, /// VM KVM state. pub vm_state: VmState, /// Vcpu states. @@ -736,6 +739,7 @@ mod tests { device_states: states, memory_state, vcpu_states, + kvm_state: Default::default(), vm_info: VmInfo { mem_size_mib: 1u64, ..Default::default() diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs new file mode 100644 index 00000000000..985a9fae1b3 --- /dev/null +++ b/src/vmm/src/vstate/kvm.rs @@ -0,0 +1,205 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use kvm_bindings::KVM_API_VERSION; +#[cfg(target_arch = "x86_64")] +use kvm_bindings::{CpuId, MsrList, KVM_MAX_CPUID_ENTRIES}; +use kvm_ioctls::Kvm as KvmFd; +use serde::{Deserialize, Serialize}; + +use crate::cpu_config::templates::KvmCapability; +use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; + +/// Errors associated with the wrappers over KVM ioctls. +/// Needs `rustfmt::skip` to make multiline comments work +#[rustfmt::skip] +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum KvmError { + /// The host kernel reports an invalid KVM API version: {0} + ApiVersion(i32), + /// Missing KVM capabilities: {0:#x?} + Capabilities(u32), + /** Error creating KVM object: {0} Make sure the user launching the firecracker process is \ + configured on the /dev/kvm file's ACL. */ + Kvm(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to get MSR index list to save into snapshots: {0} + GetMsrsToSave(crate::arch::x86_64::msr::MsrError), + #[cfg(target_arch = "x86_64")] + /// Failed to get supported cpuid: {0} + GetSupportedCpuId(kvm_ioctls::Error), + /// The number of configured slots is bigger than the maximum reported by KVM + NotEnoughMemorySlots, +} + +/// Struct with kvm fd and kvm associated paramenters. +#[derive(Debug)] +pub struct Kvm { + /// KVM fd. + pub fd: KvmFd, + /// Maximum number of memory slots allowed by KVM. + pub max_memslots: usize, + /// Additional capabilities that were specified in cpu template. + pub kvm_cap_modifiers: Vec, + + #[cfg(target_arch = "x86_64")] + /// Supported CpuIds. + pub supported_cpuid: CpuId, + #[cfg(target_arch = "x86_64")] + /// Msrs needed to be saved on snapshot creation. + pub msrs_to_save: MsrList, +} + +impl Kvm { + /// Create `Kvm` struct. + pub fn new(kvm_cap_modifiers: Vec) -> Result { + let kvm_fd = KvmFd::new().map_err(KvmError::Kvm)?; + + // Check that KVM has the correct version. + // Safe to cast because this is a constant. + #[allow(clippy::cast_possible_wrap)] + if kvm_fd.get_api_version() != KVM_API_VERSION as i32 { + return Err(KvmError::ApiVersion(kvm_fd.get_api_version())); + } + + let total_caps = Self::combine_capabilities(&kvm_cap_modifiers); + // Check that all desired capabilities are supported. + Self::check_capabilities(&kvm_fd, &total_caps).map_err(KvmError::Capabilities)?; + + let max_memslots = kvm_fd.get_nr_memslots(); + + #[cfg(target_arch = "aarch64")] + { + Ok(Self { + fd: kvm_fd, + max_memslots, + kvm_cap_modifiers, + }) + } + + #[cfg(target_arch = "x86_64")] + { + let supported_cpuid = kvm_fd + .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) + .map_err(KvmError::GetSupportedCpuId)?; + let msrs_to_save = crate::arch::x86_64::msr::get_msrs_to_save(&kvm_fd) + .map_err(KvmError::GetMsrsToSave)?; + + Ok(Kvm { + fd: kvm_fd, + max_memslots, + kvm_cap_modifiers, + supported_cpuid, + msrs_to_save, + }) + } + } + + /// Check guest memory does not have more regions than kvm allows. + pub fn check_memory(&self, guest_mem: &GuestMemoryMmap) -> Result<(), KvmError> { + if guest_mem.num_regions() > self.max_memslots { + Err(KvmError::NotEnoughMemorySlots) + } else { + Ok(()) + } + } + + fn combine_capabilities(kvm_cap_modifiers: &[KvmCapability]) -> Vec { + let mut total_caps = Self::DEFAULT_CAPABILITIES.to_vec(); + for modifier in kvm_cap_modifiers.iter() { + match modifier { + KvmCapability::Add(cap) => { + if !total_caps.contains(cap) { + total_caps.push(*cap); + } + } + KvmCapability::Remove(cap) => { + if let Some(pos) = total_caps.iter().position(|c| c == cap) { + total_caps.swap_remove(pos); + } + } + } + } + total_caps + } + + fn check_capabilities(kvm_fd: &KvmFd, capabilities: &[u32]) -> Result<(), u32> { + for cap in capabilities { + // If capability is not supported kernel will return 0. + if kvm_fd.check_extension_raw(u64::from(*cap)) == 0 { + return Err(*cap); + } + } + Ok(()) + } + + /// Saves and returns the Kvm state. + pub fn save_state(&self) -> KvmState { + KvmState { + kvm_cap_modifiers: self.kvm_cap_modifiers.clone(), + } + } +} + +#[cfg(target_arch = "aarch64")] +impl Kvm { + const DEFAULT_CAPABILITIES: [u32; 7] = [ + kvm_bindings::KVM_CAP_IOEVENTFD, + kvm_bindings::KVM_CAP_IRQFD, + kvm_bindings::KVM_CAP_USER_MEMORY, + kvm_bindings::KVM_CAP_ARM_PSCI_0_2, + kvm_bindings::KVM_CAP_DEVICE_CTRL, + kvm_bindings::KVM_CAP_MP_STATE, + kvm_bindings::KVM_CAP_ONE_REG, + ]; +} + +#[cfg(target_arch = "x86_64")] +impl Kvm { + const DEFAULT_CAPABILITIES: [u32; 14] = [ + kvm_bindings::KVM_CAP_IRQCHIP, + kvm_bindings::KVM_CAP_IOEVENTFD, + kvm_bindings::KVM_CAP_IRQFD, + kvm_bindings::KVM_CAP_USER_MEMORY, + kvm_bindings::KVM_CAP_SET_TSS_ADDR, + kvm_bindings::KVM_CAP_PIT2, + kvm_bindings::KVM_CAP_PIT_STATE2, + kvm_bindings::KVM_CAP_ADJUST_CLOCK, + kvm_bindings::KVM_CAP_DEBUGREGS, + kvm_bindings::KVM_CAP_MP_STATE, + kvm_bindings::KVM_CAP_VCPU_EVENTS, + kvm_bindings::KVM_CAP_XCRS, + kvm_bindings::KVM_CAP_XSAVE, + kvm_bindings::KVM_CAP_EXT_CPUID, + ]; +} + +/// Structure holding an general specific VM state. +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct KvmState { + /// Additional capabilities that were specified in cpu template. + pub kvm_cap_modifiers: Vec, +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + #[test] + fn test_combine_capabilities() { + // Default caps for x86_64 and aarch64 both have KVM_CAP_IOEVENTFD and don't have + // KVM_CAP_IOMMU caps. + let additional_capabilities = vec![ + KvmCapability::Add(kvm_bindings::KVM_CAP_IOMMU), + KvmCapability::Remove(kvm_bindings::KVM_CAP_IOEVENTFD), + ]; + + let combined_caps = Kvm::combine_capabilities(&additional_capabilities); + assert!(combined_caps + .iter() + .any(|c| *c == kvm_bindings::KVM_CAP_IOMMU)); + assert!(!combined_caps + .iter() + .any(|c| *c == kvm_bindings::KVM_CAP_IOEVENTFD)); + } +} diff --git a/src/vmm/src/vstate/mod.rs b/src/vmm/src/vstate/mod.rs index 32d7bd7ea7f..47458835e04 100644 --- a/src/vmm/src/vstate/mod.rs +++ b/src/vmm/src/vstate/mod.rs @@ -1,6 +1,8 @@ // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +/// Module with Kvm implementation. +pub mod kvm; /// Module with GuestMemory implementation. pub mod memory; /// Module with Vcpu implementation. diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 4e006f196d0..4097ef59044 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -22,6 +22,7 @@ use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; use crate::cpu_config::templates::CpuConfiguration; use crate::logger::{error, IncMetric, METRICS}; use crate::vcpu::{VcpuConfig, VcpuError}; +use crate::vstate::kvm::Kvm; use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuEmulation; use crate::vstate::vm::Vm; @@ -77,7 +78,7 @@ impl KvmVcpu { /// /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. - pub fn new(index: u8, vm: &Vm) -> Result { + pub fn new(index: u8, vm: &Vm, _: &Kvm) -> Result { let kvm_vcpu = vm .fd() .create_vcpu(index.into()) @@ -305,26 +306,27 @@ mod tests { use crate::cpu_config::aarch64::CpuConfiguration; use crate::cpu_config::templates::RegisterValueFilter; use crate::vcpu::VcpuConfig; + use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; - use crate::vstate::vm::tests::setup_vm; + use crate::vstate::vm::tests::setup_vm_with_memory; use crate::vstate::vm::Vm; - fn setup_vcpu(mem_size: usize) -> (Vm, KvmVcpu, GuestMemoryMmap) { - let (mut vm, vm_mem) = setup_vm(mem_size); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { + let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); + let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); - (vm, vcpu, vm_mem) + (kvm, vm, vcpu, vm_mem) } #[test] fn test_create_vcpu() { - let (vm, _) = setup_vm(0x1000); + let (kvm, vm, _) = setup_vm_with_memory(0x1000); unsafe { libc::close(vm.fd().as_raw_fd()) }; - let err = KvmVcpu::new(0, &vm); + let err = KvmVcpu::new(0, &vm, &kvm); assert_eq!( err.err().unwrap().to_string(), "Error creating vcpu: Bad file descriptor (os error 9)".to_string() @@ -336,7 +338,7 @@ mod tests { #[test] fn test_configure_vcpu() { - let (_vm, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (_, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); let vcpu_config = VcpuConfig { vcpu_count: 1, @@ -371,8 +373,8 @@ mod tests { #[test] fn test_init_vcpu() { - let (mut vm, _vm_mem) = setup_vm(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); vm.setup_irqchip(1).unwrap(); // KVM_ARM_VCPU_PSCI_0_2 is set by default. @@ -390,8 +392,8 @@ mod tests { #[test] fn test_vcpu_save_restore_state() { - let (mut vm, _vm_mem) = setup_vm(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); vm.setup_irqchip(1).unwrap(); // Calling KVM_GET_REGLIST before KVM_VCPU_INIT will result in error. @@ -434,8 +436,8 @@ mod tests { // // This should fail with ENOEXEC. // https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165 - let (mut vm, _vm_mem) = setup_vm(0x1000); - let vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); + let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu.dump_cpu_config().unwrap_err(); @@ -444,8 +446,8 @@ mod tests { #[test] fn test_dump_cpu_config_after_init() { // Test `dump_cpu_config()` after `KVM_VCPU_INIT`. - let (mut vm, _vm_mem) = setup_vm(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu.init(&[]).unwrap(); @@ -454,10 +456,10 @@ mod tests { #[test] fn test_setup_non_boot_vcpu() { - let (vm, _) = setup_vm(0x1000); - let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu1 = KvmVcpu::new(0, &vm, &kvm).unwrap(); vcpu1.init(&[]).unwrap(); - let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap(); + let mut vcpu2 = KvmVcpu::new(1, &vm, &kvm).unwrap(); vcpu2.init(&[]).unwrap(); } @@ -466,7 +468,7 @@ mod tests { // Test `get_regs()` with valid register IDs. // - X0: 0x6030 0000 0010 0000 // - X1: 0x6030 0000 0010 0002 - let (_, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu, _) = setup_vcpu(0x10000); let reg_list = Vec::::from([0x6030000000100000, 0x6030000000100002]); get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap(); } @@ -474,7 +476,7 @@ mod tests { #[test] fn test_get_invalid_regs() { // Test `get_regs()` with invalid register IDs. - let (_, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu, _) = setup_vcpu(0x10000); let reg_list = Vec::::from([0x6030000000100001, 0x6030000000100003]); get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap_err(); } diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index ddfeda21b4c..3d8877285a4 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -44,6 +44,8 @@ pub use aarch64::{KvmVcpuError, *}; #[cfg(target_arch = "x86_64")] pub use x86_64::{KvmVcpuError, *}; +use super::kvm::Kvm; + /// Signal number (SIGRTMIN) used to kick Vcpus. pub const VCPU_RTSIG_OFFSET: i32 = 0; @@ -212,10 +214,10 @@ impl Vcpu { /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. /// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits. - pub fn new(index: u8, vm: &Vm, exit_evt: EventFd) -> Result { + pub fn new(index: u8, vm: &Vm, kvm: &Kvm, exit_evt: EventFd) -> Result { let (event_sender, event_receiver) = channel(); let (response_sender, response_receiver) = channel(); - let kvm_vcpu = KvmVcpu::new(index, vm).unwrap(); + let kvm_vcpu = KvmVcpu::new(index, vm, kvm).unwrap(); Ok(Vcpu { exit_evt, @@ -777,13 +779,13 @@ pub(crate) mod tests { use crate::utils::signal::validate_signal_num; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuError as EmulationError; - use crate::vstate::vm::tests::setup_vm; + use crate::vstate::vm::tests::setup_vm_with_memory; use crate::vstate::vm::Vm; use crate::RECV_TIMEOUT_SEC; #[test] fn test_handle_kvm_exit() { - let (_vm, mut vcpu, _vm_mem) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _vm_mem) = setup_vcpu(0x1000); let res = handle_kvm_exit(&mut vcpu.kvm_vcpu.peripherals, Ok(VcpuExit::Hlt)); assert_eq!(res.unwrap(), VcpuEmulation::Stopped); @@ -918,14 +920,14 @@ pub(crate) mod tests { // Auxiliary function being used throughout the tests. #[allow(unused_mut)] - pub(crate) fn setup_vcpu(mem_size: usize) -> (Vm, Vcpu, GuestMemoryMmap) { - let (mut vm, gm) = setup_vm(mem_size); + pub(crate) fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, Vcpu, GuestMemoryMmap) { + let (kvm, mut vm, gm) = setup_vm_with_memory(mem_size); let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); #[cfg(target_arch = "aarch64")] let vcpu = { - let mut vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); + let mut vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap(); vcpu.kvm_vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu @@ -933,9 +935,9 @@ pub(crate) mod tests { #[cfg(target_arch = "x86_64")] let vcpu = { vm.setup_irqchip().unwrap(); - Vcpu::new(1, &vm, exit_evt).unwrap() + Vcpu::new(1, &vm, &kvm, exit_evt).unwrap() }; - (vm, vcpu, gm) + (kvm, vm, vcpu, gm) } fn load_good_kernel(vm_memory: &GuestMemoryMmap) -> GuestAddress { @@ -970,7 +972,7 @@ pub(crate) mod tests { Vcpu::register_kick_signal_handler(); // Need enough mem to boot linux. let mem_size = 64 << 20; - let (_vm, mut vcpu, vm_mem) = setup_vcpu(mem_size); + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(mem_size); let vcpu_exit_evt = vcpu.exit_evt.try_clone().unwrap(); @@ -988,7 +990,7 @@ pub(crate) mod tests { vcpu_count: 1, smt: false, cpu_config: CpuConfiguration { - cpuid: Cpuid::try_from(_vm.supported_cpuid().clone()).unwrap(), + cpuid: Cpuid::try_from(kvm.supported_cpuid.clone()).unwrap(), msrs: BTreeMap::new(), }, }, @@ -1022,7 +1024,7 @@ pub(crate) mod tests { #[test] fn test_set_mmio_bus() { - let (_, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _) = setup_vcpu(0x1000); assert!(vcpu.kvm_vcpu.peripherals.mmio_bus.is_none()); vcpu.set_mmio_bus(crate::devices::Bus::new()); assert!(vcpu.kvm_vcpu.peripherals.mmio_bus.is_some()); @@ -1030,7 +1032,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_tls() { - let (_, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _) = setup_vcpu(0x1000); // Running on the TLS vcpu should fail before we actually initialize it. unsafe { @@ -1061,7 +1063,7 @@ pub(crate) mod tests { #[test] fn test_invalid_tls() { - let (_, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _) = setup_vcpu(0x1000); // Initialize vcpu TLS. vcpu.init_thread_local_data().unwrap(); // Trying to initialize non-empty TLS should error. @@ -1071,7 +1073,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_kick() { Vcpu::register_kick_signal_handler(); - let (vm, mut vcpu, _) = setup_vcpu(0x1000); + let (_, vm, mut vcpu, _) = setup_vcpu(0x1000); let mut kvm_run = kvm_ioctls::KvmRunWrapper::mmap_from_fd(&vcpu.kvm_vcpu.fd, vm.fd().run_size()) @@ -1126,7 +1128,7 @@ pub(crate) mod tests { #[test] fn test_immediate_exit_shortcircuits_execution() { - let (_vm, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _) = setup_vcpu(0x1000); vcpu.kvm_vcpu.fd.set_kvm_immediate_exit(1); // Set a dummy value to be returned by the emulate call diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 4043691130d..39ff0879ee8 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -23,6 +23,7 @@ use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError}; use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError}; use crate::cpu_config::x86_64::{cpuid, CpuConfiguration}; use crate::logger::{IncMetric, METRICS}; +use crate::vstate::kvm::Kvm; use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation}; use crate::vstate::vm::Vm; @@ -164,7 +165,7 @@ impl KvmVcpu { /// /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. - pub fn new(index: u8, vm: &Vm) -> Result { + pub fn new(index: u8, vm: &Vm, kvm: &Kvm) -> Result { let kvm_vcpu = vm .fd() .create_vcpu(index.into()) @@ -174,7 +175,7 @@ impl KvmVcpu { index, fd: kvm_vcpu, peripherals: Default::default(), - msrs_to_save: vm.msrs_to_save().as_slice().to_vec(), + msrs_to_save: kvm.msrs_to_save.as_slice().to_vec(), }) } @@ -716,7 +717,7 @@ mod tests { #![allow(clippy::undocumented_unsafe_blocks)] use kvm_bindings::kvm_msr_entry; - use kvm_ioctls::{Cap, Kvm}; + use kvm_ioctls::Cap; use super::*; use crate::arch::x86_64::cpu_model::CpuModel; @@ -725,7 +726,7 @@ mod tests { StaticCpuTemplate, }; use crate::cpu_config::x86_64::cpuid::{Cpuid, CpuidEntry, CpuidKey}; - use crate::vstate::vm::tests::setup_vm; + use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; use crate::vstate::vm::Vm; impl Default for VcpuState { @@ -746,11 +747,11 @@ mod tests { } } - fn setup_vcpu(mem_size: usize) -> (Vm, KvmVcpu, GuestMemoryMmap) { - let (vm, vm_mem) = setup_vm(mem_size); + fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { + let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size); vm.setup_irqchip().unwrap(); - let vcpu = KvmVcpu::new(0, &vm).unwrap(); - (vm, vcpu, vm_mem) + let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + (kvm, vm, vcpu, vm_mem) } fn is_at_least_cascade_lake() -> bool { @@ -765,11 +766,11 @@ mod tests { } fn create_vcpu_config( - vm: &Vm, + kvm: &Kvm, vcpu: &KvmVcpu, template: &CustomCpuTemplate, ) -> Result { - let cpuid = Cpuid::try_from(vm.supported_cpuid().clone()) + let cpuid = Cpuid::try_from(kvm.supported_cpuid.clone()) .map_err(GuestConfigError::CpuidFromKvmCpuid)?; let msrs = vcpu .get_msrs(template.msr_index_iter()) @@ -785,19 +786,19 @@ mod tests { #[test] fn test_configure_vcpu() { - let (vm, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); - let vcpu_config = create_vcpu_config(&vm, &vcpu, &CustomCpuTemplate::default()).unwrap(); + let vcpu_config = create_vcpu_config(&kvm, &vcpu, &CustomCpuTemplate::default()).unwrap(); assert_eq!( vcpu.configure(&vm_mem, GuestAddress(0), &vcpu_config,), Ok(()) ); - let try_configure = |vm: &Vm, vcpu: &mut KvmVcpu, template| -> bool { + let try_configure = |kvm: &Kvm, vcpu: &mut KvmVcpu, template| -> bool { let cpu_template = Some(CpuTemplateType::Static(template)); let template = cpu_template.get_cpu_template(); match template { - Ok(template) => match create_vcpu_config(vm, vcpu, &template) { + Ok(template) => match create_vcpu_config(kvm, vcpu, &template) { Ok(config) => vcpu .configure( &vm_mem, @@ -812,19 +813,19 @@ mod tests { }; // Test configure while using the T2 template. - let t2_res = try_configure(&vm, &mut vcpu, StaticCpuTemplate::T2); + let t2_res = try_configure(&kvm, &mut vcpu, StaticCpuTemplate::T2); // Test configure while using the C3 template. - let c3_res = try_configure(&vm, &mut vcpu, StaticCpuTemplate::C3); + let c3_res = try_configure(&kvm, &mut vcpu, StaticCpuTemplate::C3); // Test configure while using the T2S template. - let t2s_res = try_configure(&vm, &mut vcpu, StaticCpuTemplate::T2S); + let t2s_res = try_configure(&kvm, &mut vcpu, StaticCpuTemplate::T2S); // Test configure while using the T2CL template. - let t2cl_res = try_configure(&vm, &mut vcpu, StaticCpuTemplate::T2CL); + let t2cl_res = try_configure(&kvm, &mut vcpu, StaticCpuTemplate::T2CL); // Test configure while using the T2S template. - let t2a_res = try_configure(&vm, &mut vcpu, StaticCpuTemplate::T2A); + let t2a_res = try_configure(&kvm, &mut vcpu, StaticCpuTemplate::T2A); match &cpuid::common::get_vendor_id_from_host().unwrap() { cpuid::VENDOR_ID_INTEL => { @@ -857,8 +858,8 @@ mod tests { #[test] fn test_vcpu_cpuid_restore() { - let (vm, vcpu, _mem) = setup_vcpu(0x10000); - vcpu.fd.set_cpuid2(vm.supported_cpuid()).unwrap(); + let (kvm, _, vcpu, _mem) = setup_vcpu(0x10000); + vcpu.fd.set_cpuid2(&kvm.supported_cpuid).unwrap(); // Mutate the CPUID. // Leaf 0x3 / EAX that is an unused (reserved to be accurate) register, so it's harmless. @@ -875,7 +876,7 @@ mod tests { drop(vcpu); // Restore the state into a new vcpu. - let (_vm, vcpu, _mem) = setup_vcpu(0x10000); + let (_, _vm, vcpu, _mem) = setup_vcpu(0x10000); let result2 = vcpu.restore_state(&state); assert!(result2.is_ok(), "{}", result2.unwrap_err()); @@ -895,12 +896,12 @@ mod tests { #[test] fn test_empty_cpuid_entries_removed() { // Test that `get_cpuid()` removes zeroed empty entries from the `KVM_GET_CPUID2` result. - let (vm, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); let vcpu_config = VcpuConfig { vcpu_count: 1, smt: false, cpu_config: CpuConfiguration { - cpuid: Cpuid::try_from(vm.supported_cpuid().clone()).unwrap(), + cpuid: Cpuid::try_from(kvm.supported_cpuid.clone()).unwrap(), msrs: BTreeMap::new(), }, }; @@ -946,7 +947,7 @@ mod tests { // Since `KVM_SET_CPUID2` has not been called before vcpu configuration, all leaves should // be filled with zero. Therefore, `KvmVcpu::dump_cpu_config()` should fail with CPUID type // conversion error due to the lack of brand string info in leaf 0x0. - let (_, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu, _) = setup_vcpu(0x10000); match vcpu.dump_cpu_config() { Err(KvmVcpuError::ConvertCpuidType(_)) => (), Err(err) => panic!("Unexpected error: {err}"), @@ -957,12 +958,12 @@ mod tests { #[test] fn test_dump_cpu_config_with_configured_vcpu() { // Test `dump_cpu_config()` after vcpu configuration. - let (vm, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); let vcpu_config = VcpuConfig { vcpu_count: 1, smt: false, cpu_config: CpuConfiguration { - cpuid: Cpuid::try_from(vm.supported_cpuid().clone()).unwrap(), + cpuid: Cpuid::try_from(kvm.supported_cpuid.clone()).unwrap(), msrs: BTreeMap::new(), }, }; @@ -976,7 +977,7 @@ mod tests { fn test_is_tsc_scaling_required() { // Test `is_tsc_scaling_required` as if it were on the same // CPU model as the one in the snapshot state. - let (_vm, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu, _) = setup_vcpu(0x1000); { // The frequency difference is within tolerance. @@ -1015,7 +1016,7 @@ mod tests { #[test] fn test_set_tsc() { - let (vm, vcpu, _) = setup_vcpu(0x1000); + let (kvm, _, vcpu, _) = setup_vcpu(0x1000); let mut state = vcpu.save_state().unwrap(); state.tsc_khz = Some( state.tsc_khz.unwrap() @@ -1024,9 +1025,9 @@ mod tests { * 2, ); - if vm.fd().check_extension(Cap::TscControl) { + if kvm.fd.check_extension(Cap::TscControl) { vcpu.set_tsc_khz(state.tsc_khz.unwrap()).unwrap(); - if vm.fd().check_extension(Cap::GetTscKhz) { + if kvm.fd.check_extension(Cap::GetTscKhz) { assert_eq!(vcpu.get_tsc_khz().ok(), state.tsc_khz); } else { vcpu.get_tsc_khz().unwrap_err(); @@ -1040,7 +1041,7 @@ mod tests { fn test_get_msrs_with_msrs_to_save() { // Test `get_msrs()` with the MSR indices that should be serialized into snapshots. // The MSR indices should be valid and this test should succeed. - let (_, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu, _) = setup_vcpu(0x1000); vcpu.get_msrs(vcpu.msrs_to_save.iter().copied()).unwrap(); } @@ -1048,7 +1049,7 @@ mod tests { fn test_get_msrs_with_msrs_to_dump() { // Test `get_msrs()` with the MSR indices that should be dumped. // All the MSR indices should be valid and the call should succeed. - let (_, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu, _) = setup_vcpu(0x1000); let kvm = kvm_ioctls::Kvm::new().unwrap(); let msrs_to_dump = crate::arch::x86_64::msr::get_msrs_to_dump(&kvm).unwrap(); @@ -1061,7 +1062,7 @@ mod tests { // Test `get_msrs()` with unsupported MSR indices. This should return `VcpuGetMsr` error // that happens when `KVM_GET_MSRS` fails to populate MSR values in the middle and exits. // Currently, MSR indices 2..=4 are not listed as supported MSRs. - let (_, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu, _) = setup_vcpu(0x1000); let msr_index_list: Vec = vec![2, 3, 4]; match vcpu.get_msrs(msr_index_list.iter().copied()) { Err(KvmVcpuError::VcpuGetMsr(_)) => (), @@ -1167,13 +1168,11 @@ mod tests { #[test] fn test_get_msr_chunks_preserved_order() { // Regression test for #4666 - - let kvm = Kvm::new().unwrap(); - let vm = Vm::new(Vec::new()).unwrap(); - let vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, vm) = setup_vm(); + let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); // The list of supported MSR indices, in the order they were returned by KVM - let msrs_to_save = crate::arch::x86_64::msr::get_msrs_to_save(&kvm).unwrap(); + let msrs_to_save = kvm.msrs_to_save; // The MSRs after processing. The order should be identical to the one returned by KVM, with // the exception of deferred MSRs, which should be moved to the end (but show up in the same // order as they are listed in [`DEFERRED_MSRS`]. diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index d213d4d7bb6..1bcf191b8b9 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -10,21 +10,21 @@ use std::fmt; #[cfg(target_arch = "x86_64")] use kvm_bindings::{ - kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, CpuId, MsrList, - KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, - KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY, + kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE, + KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, }; -use kvm_bindings::{kvm_userspace_memory_region, KVM_API_VERSION, KVM_MEM_LOG_DIRTY_PAGES}; -use kvm_ioctls::{Kvm, VmFd}; +use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; +// use kvm_ioctls::{Kvm, VmFd}; +use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::GICDevice; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::GicState; -use crate::cpu_config::templates::KvmCapability; #[cfg(target_arch = "x86_64")] use crate::utils::u64_to_usize; +use crate::vstate::kvm::Kvm; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; /// Errors associated with the wrappers over KVM ioctls. @@ -32,18 +32,6 @@ use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRe #[rustfmt::skip] #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] pub enum VmError { - /// The host kernel reports an invalid KVM API version: {0} - ApiVersion(i32), - /// Missing KVM capabilities: {0:#x?} - Capabilities(u32), - /** Error creating KVM object: {0} Make sure the user launching the firecracker process is \ - configured on the /dev/kvm file's ACL. */ - Kvm(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get MSR index list to save into snapshots: {0} - GetMsrsToSave(#[from] crate::arch::x86_64::msr::MsrError), - /// The number of configured slots is bigger than the maximum reported by KVM - NotEnoughMemorySlots, /// Cannot set the memory regions: {0} SetUserMemoryRegion(kvm_ioctls::Error), #[cfg(target_arch = "aarch64")] @@ -112,16 +100,6 @@ pub enum RestoreStateError { #[derive(Debug)] pub struct Vm { fd: VmFd, - max_memslots: usize, - - /// Additional capabilities that were specified in cpu template. - pub kvm_cap_modifiers: Vec, - - // X86 specific fields. - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - supported_cpuid: CpuId, - #[cfg(target_arch = "x86_64")] - msrs_to_save: MsrList, // Arm specific fields. // On aarch64 we need to keep around the fd obtained by creating the VGIC device. @@ -131,79 +109,23 @@ pub struct Vm { /// Contains Vm functions that are usable across CPU architectures impl Vm { - /// Constructs a new `Vm` using the given `Kvm` instance. - pub fn new(kvm_cap_modifiers: Vec) -> Result { - let kvm = Kvm::new().map_err(VmError::Kvm)?; - - // Check that KVM has the correct version. - // Safe to cast because this is a constant. - #[allow(clippy::cast_possible_wrap)] - if kvm.get_api_version() != KVM_API_VERSION as i32 { - return Err(VmError::ApiVersion(kvm.get_api_version())); - } - - let total_caps = Self::combine_capabilities(&kvm_cap_modifiers); - // Check that all desired capabilities are supported. - Self::check_capabilities(&kvm, &total_caps).map_err(VmError::Capabilities)?; - - let max_memslots = kvm.get_nr_memslots(); + /// Create a new `Vm` struct. + pub fn new(kvm: &Kvm) -> Result { // Create fd for interacting with kvm-vm specific functions. - let vm_fd = kvm.create_vm().map_err(VmError::VmFd)?; + let vm_fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; #[cfg(target_arch = "aarch64")] { Ok(Vm { fd: vm_fd, - max_memslots, - kvm_cap_modifiers, irqchip_handle: None, }) } #[cfg(target_arch = "x86_64")] { - let supported_cpuid = kvm - .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) - .map_err(VmError::VmFd)?; - let msrs_to_save = crate::arch::x86_64::msr::get_msrs_to_save(&kvm)?; - - Ok(Vm { - fd: vm_fd, - max_memslots, - kvm_cap_modifiers, - supported_cpuid, - msrs_to_save, - }) - } - } - - fn combine_capabilities(kvm_cap_modifiers: &[KvmCapability]) -> Vec { - let mut total_caps = Self::DEFAULT_CAPABILITIES.to_vec(); - for modifier in kvm_cap_modifiers.iter() { - match modifier { - KvmCapability::Add(cap) => { - if !total_caps.iter().any(|c| c == cap) { - total_caps.push(*cap); - } - } - KvmCapability::Remove(cap) => { - if let Some(pos) = total_caps.iter().position(|c| c == cap) { - total_caps.remove(pos); - } - } - } + Ok(Vm { fd: vm_fd }) } - total_caps - } - - fn check_capabilities(kvm: &Kvm, capabilities: &[u32]) -> Result<(), u32> { - for cap in capabilities { - // If capability is not supported kernel will return 0. - if kvm.check_extension_raw(u64::from(*cap)) == 0 { - return Err(*cap); - } - } - Ok(()) } /// Initializes the guest memory. @@ -212,9 +134,6 @@ impl Vm { guest_mem: &GuestMemoryMmap, track_dirty_pages: bool, ) -> Result<(), VmError> { - if guest_mem.num_regions() > self.max_memslots { - return Err(VmError::NotEnoughMemorySlots); - } self.set_kvm_memory_regions(guest_mem, track_dirty_pages)?; #[cfg(target_arch = "x86_64")] self.fd @@ -261,16 +180,6 @@ impl Vm { #[cfg(target_arch = "aarch64")] impl Vm { - const DEFAULT_CAPABILITIES: [u32; 7] = [ - kvm_bindings::KVM_CAP_IOEVENTFD, - kvm_bindings::KVM_CAP_IRQFD, - kvm_bindings::KVM_CAP_USER_MEMORY, - kvm_bindings::KVM_CAP_ARM_PSCI_0_2, - kvm_bindings::KVM_CAP_DEVICE_CTRL, - kvm_bindings::KVM_CAP_MP_STATE, - kvm_bindings::KVM_CAP_ONE_REG, - ]; - /// Creates the GIC (Global Interrupt Controller). pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), VmError> { self.irqchip_handle = Some( @@ -292,7 +201,6 @@ impl Vm { .get_irqchip() .save_device(mpidrs) .map_err(VmError::SaveGic)?, - kvm_cap_modifiers: self.kvm_cap_modifiers.clone(), }) } @@ -319,39 +227,10 @@ impl Vm { pub struct VmState { /// GIC state. pub gic: GicState, - /// Additional capabilities that were specified in cpu template. - pub kvm_cap_modifiers: Vec, } #[cfg(target_arch = "x86_64")] impl Vm { - const DEFAULT_CAPABILITIES: [u32; 14] = [ - kvm_bindings::KVM_CAP_IRQCHIP, - kvm_bindings::KVM_CAP_IOEVENTFD, - kvm_bindings::KVM_CAP_IRQFD, - kvm_bindings::KVM_CAP_USER_MEMORY, - kvm_bindings::KVM_CAP_SET_TSS_ADDR, - kvm_bindings::KVM_CAP_PIT2, - kvm_bindings::KVM_CAP_PIT_STATE2, - kvm_bindings::KVM_CAP_ADJUST_CLOCK, - kvm_bindings::KVM_CAP_DEBUGREGS, - kvm_bindings::KVM_CAP_MP_STATE, - kvm_bindings::KVM_CAP_VCPU_EVENTS, - kvm_bindings::KVM_CAP_XCRS, - kvm_bindings::KVM_CAP_XSAVE, - kvm_bindings::KVM_CAP_EXT_CPUID, - ]; - - /// Returns a ref to the supported `CpuId` for this Vm. - pub fn supported_cpuid(&self) -> &CpuId { - &self.supported_cpuid - } - - /// Returns a ref to the list of serializable MSR indices. - pub fn msrs_to_save(&self) -> &MsrList { - &self.msrs_to_save - } - /// Restores the KVM VM state. /// /// # Errors @@ -431,7 +310,6 @@ impl Vm { pic_master, pic_slave, ioapic, - kvm_cap_modifiers: self.kvm_cap_modifiers.clone(), }) } } @@ -447,9 +325,6 @@ pub struct VmState { // TODO: rename this field to adopt inclusive language once Linux updates it, too. pic_slave: kvm_irqchip, ioapic: kvm_irqchip, - - /// Additional capabilities that were specified in cpu template. - pub kvm_cap_modifiers: Vec, } #[cfg(target_arch = "x86_64")] @@ -474,43 +349,30 @@ pub(crate) mod tests { use crate::vstate::memory::GuestMemoryMmap; // Auxiliary function being used throughout the tests. - pub(crate) fn setup_vm(mem_size: usize) -> (Vm, GuestMemoryMmap) { - let gm = single_region_mem(mem_size); + pub(crate) fn setup_vm() -> (Kvm, Vm) { + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + let vm = Vm::new(&kvm).expect("Cannot create new vm"); + (kvm, vm) + } - let vm = Vm::new(vec![]).expect("Cannot create new vm"); + // Auxiliary function being used throughout the tests. + pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm, GuestMemoryMmap) { + let (kvm, vm) = setup_vm(); + let gm = single_region_mem(mem_size); vm.memory_init(&gm, false).unwrap(); - - (vm, gm) + (kvm, vm, gm) } #[test] fn test_new() { // Testing with a valid /dev/kvm descriptor. - Vm::new(vec![]).unwrap(); - } - - #[test] - fn test_combine_capabilities() { - // Default caps for x86_64 and aarch64 both have KVM_CAP_IOEVENTFD and don't have - // KVM_CAP_IOMMU caps. - let additional_capabilities = vec![ - KvmCapability::Add(kvm_bindings::KVM_CAP_IOMMU), - KvmCapability::Remove(kvm_bindings::KVM_CAP_IOEVENTFD), - ]; - - let combined_caps = Vm::combine_capabilities(&additional_capabilities); - assert!(combined_caps - .iter() - .any(|c| *c == kvm_bindings::KVM_CAP_IOMMU)); - assert!(!combined_caps - .iter() - .any(|c| *c == kvm_bindings::KVM_CAP_IOEVENTFD)); + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + Vm::new(&kvm).unwrap(); } #[test] fn test_vm_memory_init() { - let vm = Vm::new(vec![]).expect("Cannot create new vm"); - + let (_, vm) = setup_vm(); // Create valid memory region and test that the initialization is successful. let gm = single_region_mem(0x1000); vm.memory_init(&gm, true).unwrap(); @@ -519,11 +381,11 @@ pub(crate) mod tests { #[cfg(target_arch = "x86_64")] #[test] fn test_vm_save_restore_state() { - let vm = Vm::new(vec![]).expect("new vm failed"); + let (_, vm) = setup_vm(); // Irqchips, clock and pitstate are not configured so trying to save state should fail. vm.save_state().unwrap_err(); - let (vm, _mem) = setup_vm(0x1000); + let (_, vm, _mem) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let vm_state = vm.save_state().unwrap(); @@ -536,7 +398,7 @@ pub(crate) mod tests { assert_eq!(vm_state.pic_slave.chip_id, KVM_IRQCHIP_PIC_SLAVE); assert_eq!(vm_state.ioapic.chip_id, KVM_IRQCHIP_IOAPIC); - let (mut vm, _mem) = setup_vm(0x1000); + let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); vm.restore_state(&vm_state).unwrap(); @@ -547,11 +409,11 @@ pub(crate) mod tests { fn test_vm_save_restore_state_bad_irqchip() { use kvm_bindings::KVM_NR_IRQCHIPS; - let (vm, _mem) = setup_vm(0x1000); + let (_, vm, _mem) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let mut vm_state = vm.save_state().unwrap(); - let (mut vm, _mem) = setup_vm(0x1000); + let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); // Try to restore an invalid PIC Master chip ID @@ -576,7 +438,7 @@ pub(crate) mod tests { fn test_vmstate_serde() { let mut snapshot_data = vec![0u8; 10000]; - let (mut vm, _) = setup_vm(0x1000); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let state = vm.save_state().unwrap(); Snapshot::serialize(&mut snapshot_data.as_mut_slice(), &state).unwrap(); @@ -587,7 +449,7 @@ pub(crate) mod tests { #[test] fn test_set_kvm_memory_regions() { - let vm = Vm::new(vec![]).expect("Cannot create new vm"); + let (_, vm) = setup_vm(); let gm = single_region_mem(0x1000); let res = vm.set_kvm_memory_regions(&gm, false); From d71ff8a79e5de7fff659cd953e8a591a9b78ef19 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 10 Jan 2025 11:27:02 +0000 Subject: [PATCH 171/464] feat: reset KVM_REG_ARM_PTIMER_CNT on VM boot Reset KVM_REG_ARM_PTIMER_CNT physical counter register on VM boot to avoid passing through host physical counter. Note that resetting the register on VM boot does not guarantee that VM will see the counter value 0 at startup because there is a delta in time between register reset and VM boot during which counter continues to advance. In order to check if the kernel supports the counter reset we query KVM_CAP_COUNTER_OFFSET capability and only reset the KVM_REG_ARM_PTIMER_CNT if it is present. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/regs.rs | 6 +++++ src/vmm/src/arch/aarch64/vcpu.rs | 42 ++++++++++++++++++++++++++++-- src/vmm/src/builder.rs | 29 +++++++++++++++------ src/vmm/src/vstate/kvm.rs | 18 ++++++++++++- src/vmm/src/vstate/vcpu/aarch64.rs | 9 +++++-- src/vmm/src/vstate/vcpu/mod.rs | 1 + 6 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/vmm/src/arch/aarch64/regs.rs b/src/vmm/src/arch/aarch64/regs.rs index 5238f58ba70..d844fbfb56b 100644 --- a/src/vmm/src/arch/aarch64/regs.rs +++ b/src/vmm/src/arch/aarch64/regs.rs @@ -99,6 +99,12 @@ arm64_sys_reg!(SYS_CNTV_CVAL_EL0, 3, 3, 14, 3, 2); // https://elixir.bootlin.com/linux/v6.8/source/arch/arm64/include/asm/sysreg.h#L459 arm64_sys_reg!(SYS_CNTPCT_EL0, 3, 3, 14, 0, 1); +// Physical Timer EL0 count Register +// The id of this register is same as SYS_CNTPCT_EL0, but KVM defines it +// separately, so we do as well. +// https://elixir.bootlin.com/linux/v6.12.6/source/arch/arm64/include/uapi/asm/kvm.h#L259 +arm64_sys_reg!(KVM_REG_ARM_PTIMER_CNT, 3, 3, 14, 0, 1); + // Translation Table Base Register // https://developer.arm.com/documentation/ddi0595/2021-03/AArch64-Registers/TTBR1-EL1--Translation-Table-Base-Register-1--EL1- arm64_sys_reg!(TTBR1_EL1, 3, 0, 2, 0, 1); diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 859e2da2cb6..7b34ae91896 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -13,6 +13,7 @@ use kvm_ioctls::VcpuFd; use super::get_fdt_addr; use super::regs::*; +use crate::vstate::kvm::OptionalCapabilities; use crate::vstate::memory::GuestMemoryMmap; /// Errors thrown while setting aarch64 registers. @@ -78,6 +79,7 @@ pub fn setup_boot_regs( cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap, + optional_capabilities: &OptionalCapabilities, ) -> Result<(), VcpuError> { let kreg_off = offset_of!(kvm_regs, regs); @@ -106,6 +108,23 @@ pub fn setup_boot_regs( vcpufd .set_one_reg(id, &get_fdt_addr(mem).to_le_bytes()) .map_err(|err| VcpuError::SetOneReg(id, err))?; + + // Reset the physical counter for the guest. This way we avoid guest reading + // host physical counter. + // Resetting KVM_REG_ARM_PTIMER_CNT for single vcpu is enough because there is only + // one timer struct with offsets per VM. + // Because the access to KVM_REG_ARM_PTIMER_CNT is only present starting 6.4 kernel, + // we only do the reset if KVM_CAP_COUNTER_OFFSET is present as it was added + // in the same patch series as the ability to set the KVM_REG_ARM_PTIMER_CNT register. + // Path series which introduced the needed changes: + // https://lore.kernel.org/all/20230330174800.2677007-1-maz@kernel.org/ + // Note: the value observed by the guest will still be above 0, because there is a delta + // time between this resetting and first call to KVM_RUN. + if optional_capabilities.counter_offset { + vcpufd + .set_one_reg(KVM_REG_ARM_PTIMER_CNT, &[0; 8]) + .map_err(|err| VcpuError::SetOneReg(id, err))?; + } } Ok(()) } @@ -226,8 +245,9 @@ mod tests { let vm = kvm.fd.create_vm().unwrap(); let vcpu = vm.create_vcpu(0).unwrap(); let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000); + let optional_capabilities = kvm.optional_capabilities(); - let res = setup_boot_regs(&vcpu, 0, 0x0, &mem); + let res = setup_boot_regs(&vcpu, 0, 0x0, &mem, &optional_capabilities); assert!(matches!( res.unwrap_err(), VcpuError::SetOneReg(0x6030000000100042, _) @@ -237,7 +257,25 @@ mod tests { vm.get_preferred_target(&mut kvi).unwrap(); vcpu.vcpu_init(&kvi).unwrap(); - setup_boot_regs(&vcpu, 0, 0x0, &mem).unwrap(); + setup_boot_regs(&vcpu, 0, 0x0, &mem, &optional_capabilities).unwrap(); + + // Check that the register is reset on compatible kernels. + // Because there is a delta in time between we reset the register and time we + // read it, we cannot compare with 0. Instead we compare it with meaningfully + // small value. + if optional_capabilities.counter_offset { + let mut reg_bytes = [0_u8; 8]; + vcpu.get_one_reg(SYS_CNTPCT_EL0, &mut reg_bytes).unwrap(); + let counter_value = u64::from_le_bytes(reg_bytes); + + // We are reading the SYS_CNTPCT_EL0 right after resetting it. + // If reset did happen successfully, the value should be quite small when we read it. + // If the reset did not happen, the value will be same as on the host and it surely + // will be more that MAX_VALUE. + let max_value = 1000; + + assert!(counter_value < max_value); + } } #[test] diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 6a59fe35a83..4b43e67541f 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -814,16 +814,16 @@ pub fn configure_system_for_boot( cpu_config, }; - // Configure vCPUs with normalizing and setting the generated CPU configuration. - for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .configure(vmm.guest_memory(), entry_addr, &vcpu_config) - .map_err(VmmError::VcpuConfigure) - .map_err(Internal)?; - } - #[cfg(target_arch = "x86_64")] { + // Configure vCPUs with normalizing and setting the generated CPU configuration. + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu + .configure(vmm.guest_memory(), entry_addr, &vcpu_config) + .map_err(VmmError::VcpuConfigure) + .map_err(Internal)?; + } + // Write the kernel command line to guest memory. This is x86_64 specific, since on // aarch64 the command line will be specified through the FDT. let cmdline_size = boot_cmdline @@ -858,6 +858,19 @@ pub fn configure_system_for_boot( } #[cfg(target_arch = "aarch64")] { + let optional_capabilities = vmm.kvm.optional_capabilities(); + // Configure vCPUs with normalizing and setting the generated CPU configuration. + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu + .configure( + vmm.guest_memory(), + entry_addr, + &vcpu_config, + &optional_capabilities, + ) + .map_err(VmmError::VcpuConfigure) + .map_err(Internal)?; + } let vcpu_mpidr = vcpus .iter_mut() .map(|cpu| cpu.kvm_vcpu.get_mpidr()) diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index 985a9fae1b3..59b192dbe09 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -140,7 +140,13 @@ impl Kvm { } } } - +#[cfg(target_arch = "aarch64")] +/// Optional capabilities. +#[derive(Debug, Default)] +pub struct OptionalCapabilities { + /// KVM_CAP_COUNTER_OFFSET + pub counter_offset: bool, +} #[cfg(target_arch = "aarch64")] impl Kvm { const DEFAULT_CAPABILITIES: [u32; 7] = [ @@ -152,6 +158,16 @@ impl Kvm { kvm_bindings::KVM_CAP_MP_STATE, kvm_bindings::KVM_CAP_ONE_REG, ]; + + /// Returns struct with optional capabilities statuses. + pub fn optional_capabilities(&self) -> OptionalCapabilities { + OptionalCapabilities { + counter_offset: self + .fd + .check_extension_raw(kvm_bindings::KVM_CAP_COUNTER_OFFSET.into()) + != 0, + } + } } #[cfg(target_arch = "x86_64")] diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 4097ef59044..9db1173eeb8 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -22,7 +22,7 @@ use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; use crate::cpu_config::templates::CpuConfiguration; use crate::logger::{error, IncMetric, METRICS}; use crate::vcpu::{VcpuConfig, VcpuError}; -use crate::vstate::kvm::Kvm; +use crate::vstate::kvm::{Kvm, OptionalCapabilities}; use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuEmulation; use crate::vstate::vm::Vm; @@ -116,6 +116,7 @@ impl KvmVcpu { guest_mem: &GuestMemoryMmap, kernel_load_addr: GuestAddress, vcpu_config: &VcpuConfig, + optional_capabilities: &OptionalCapabilities, ) -> Result<(), KvmVcpuError> { for reg in vcpu_config.cpu_config.regs.iter() { self.fd @@ -128,6 +129,7 @@ impl KvmVcpu { self.index, kernel_load_addr.raw_value(), guest_mem, + optional_capabilities, ) .map_err(KvmVcpuError::ConfigureRegisters)?; @@ -338,7 +340,8 @@ mod tests { #[test] fn test_configure_vcpu() { - let (_, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let optional_capabilities = kvm.optional_capabilities(); let vcpu_config = VcpuConfig { vcpu_count: 1, @@ -349,6 +352,7 @@ mod tests { &vm_mem, GuestAddress(crate::arch::get_kernel_start()), &vcpu_config, + &optional_capabilities, ) .unwrap(); @@ -358,6 +362,7 @@ mod tests { &vm_mem, GuestAddress(crate::arch::get_kernel_start()), &vcpu_config, + &optional_capabilities, ); assert_eq!( err.unwrap_err(), diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 3d8877285a4..6a6471193dc 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -1008,6 +1008,7 @@ pub(crate) mod tests { smt: false, cpu_config: crate::cpu_config::aarch64::CpuConfiguration::default(), }, + &kvm.optional_capabilities(), ) .expect("failed to configure vcpu"); From 1ab8c96245780ae1aeb43b3d8ab005c56d6ec032 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 10 Jan 2025 17:19:39 +0000 Subject: [PATCH 172/464] chore: update prod-host-setup.md with arm physical counter info Update a note about physical counter on ARM being reset instead of directly passed through on kernels with `KVM_CAP_COUNTER_OFFSET` capability. Signed-off-by: Egor Lazarchuk --- docs/prod-host-setup.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/prod-host-setup.md b/docs/prod-host-setup.md index f046e31c735..cf0ac86cf1f 100644 --- a/docs/prod-host-setup.md +++ b/docs/prod-host-setup.md @@ -328,13 +328,16 @@ For vendor-specific recommendations, please consult the resources below: - ARM: [Speculative Processor Vulnerability](https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability) -##### [ARM only] Physical counter directly passed through to the guest +##### [ARM only] VM Physical counter behaviour -On ARM, the physical counter (i.e `CNTPCT`) it is returning the -[actual EL1 physical counter value of the host][1]. From the discussions before -merging this change [upstream][2], this seems like a conscious design decision -of the ARM code contributors, giving precedence to performance over the ability -to trap and control this in the hypervisor. +On ARM, Firecracker tries to reset the `CNTPCT` physical counter on VM boot. +This is done in order to prevent VM from reading host physical counter value. +Firecracker will only try to reset the counter if the host KVM contains +`KVM_CAP_COUNTER_OFFSET` capability. This capability is only present in kernels +containing +[this](https://lore.kernel.org/all/20230330174800.2677007-1-maz@kernel.org/) +patch series (starting from 6.4 and newer). For older kernels the counter value +will be passed through from the host. ##### Verification @@ -428,6 +431,3 @@ To validate that the change took effect, the file [^1]: Look for `GRUB_CMDLINE_LINUX` in file `/etc/default/grub` in RPM-based systems, and [this doc for Ubuntu](https://wiki.ubuntu.com/Kernel/KernelBootParameters). - -[1]: https://elixir.free-electrons.com/linux/v4.14.203/source/virt/kvm/arm/hyp/timer-sr.c#L63 -[2]: https://lists.cs.columbia.edu/pipermail/kvmarm/2017-January/023323.html From 44b55ddc84f6711ab004fbf7fc43f113d0cc65d2 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 10 Jan 2025 11:37:21 +0000 Subject: [PATCH 173/464] chore: add an entry to the CHANGELOG Add an entry about physical counter reset to the CHANGELOG. Signed-off-by: Egor Lazarchuk --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 138ccd20079..00e82ee4b19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,13 @@ and this project adheres to ### Added +- [#4987](https://github.com/firecracker-microvm/firecracker/pull/4987): Reset + physical counter register (`CNTPCT_EL0`) on VM startup. This avoids VM reading + the host physical counter value. This is only possible on 6.4 and newer + kernels. For older kernels physical counter will still be passed to the guest + unmodified. See more info + [here](https://github.com/firecracker-microvm/firecracker/blob/main/docs/prod-host-setup.md#arm-only-vm-physical-counter-behaviour) + ### Changed - [#4913](https://github.com/firecracker-microvm/firecracker/pull/4913): Removed From 525e68639d18aa59820380179774a5489495f60a Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 13 Jan 2025 17:37:52 +0000 Subject: [PATCH 174/464] test: add integration test for physical counter reset Add a test to verify the reset of the physical counter on aarch64 VMs. To do this we check registers saved in the snapshot and verify the counter value is less than some reasonably small number we choose. The value is based on the observation of how much cycles it takes for a VM to boot and be snapshotted. The idea is that this value will always be smaller than the actual physical counter on the host. Signed-off-by: Egor Lazarchuk --- .../functional/test_snapshot_basic.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 4030bb4e981..875ef77dbaf 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -5,6 +5,7 @@ import filecmp import logging import os +import platform import re import shutil import time @@ -12,8 +13,11 @@ import pytest +import host_tools.cargo_build as host import host_tools.drive as drive_tools +from framework import utils from framework.microvm import SnapshotType +from framework.properties import global_props from framework.utils import check_filesystem, check_output from framework.utils_vsock import ( ECHO_SERVER_PORT, @@ -540,3 +544,56 @@ def test_vmgenid(guest_kernel_linux_6_1, rootfs, microvm_factory, snapshot_type) # Update the base for next iteration base_snapshot = snapshot + + +# TODO add `global_props.host_os == "amzn2"` condition +# once amazon linux kernels have patches. +@pytest.mark.skipif( + platform.machine() != "aarch64" or global_props.host_linux_version_tpl < (6, 4), + reason="This is aarch64 specific test and should only be run on 6.4 and later kernels", +) +def test_physical_couter_reset_aarch64(uvm_nano): + """ + Test that the CNTPCT_EL0 register is reset on VM boot. + We assume the smallest VM will not consume more than + some MAX_VALUE cycles to be created and snapshotted. + The MAX_VALUE is selected by doing a manual run of this test and + seeing what the actual counter value is. The assumption here is that + if resetting will not occur the guest counter value will be huge as it + will be a copy of host value. The host value in its turn will be huge because + it will include host OS boot + CI prep + other CI tests ... + """ + vm = uvm_nano + vm.add_net_iface() + vm.start() + + snapshot = vm.snapshot_full() + vm.kill() + snap_editor = host.get_binary("snapshot-editor") + + cntpct_el0 = hex(0x603000000013DF01) + # If a CPU runs at 3GHz, it will have a counter value of 1_000_000_000 + # in 1/3 of a second. The host surely will run for more than 1/3 second before + # executing this test. + max_value = 800_000_000 + + cmd = [ + str(snap_editor), + "info-vmstate", + "vcpu-states", + "--vmstate-path", + str(snapshot.vmstate), + ] + _, stdout, _ = utils.check_output(cmd) + + # The output will look like this: + # kvm_mp_state: 0x0 + # mpidr: 0x80000000 + # 0x6030000000100000 0x0000000e0 + # 0x6030000000100002 0xffff00fe33c0 + for line in stdout.splitlines(): + parts = line.split() + if len(parts) == 2: + reg_id, reg_value = parts + if reg_id == cntpct_el0: + assert int(reg_value, 16) < max_value From da1cc8a8cd5ff8c8edd569dd656257c68ecbc157 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 17 Jan 2025 12:45:56 +0000 Subject: [PATCH 175/464] feat: more descriptive panic messages in uffd examples Add additional info to the panic messages in uffd examples to aid with potential errors. Signed-off-by: Egor Lazarchuk --- src/firecracker/examples/uffd/uffd_utils.rs | 25 ++++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index 37aa63c62a3..8cc70ab7c21 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -61,17 +61,30 @@ impl UffdHandler { let mut message_buf = vec![0u8; 1024]; let (bytes_read, file) = stream .recv_with_fd(&mut message_buf[..]) - .expect("Cannot recv_with_fd"); + .expect("Cannot read from a stream"); message_buf.resize(bytes_read, 0); - let body = String::from_utf8(message_buf).unwrap(); - let file = file.expect("Uffd not passed through UDS!"); + let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| { + panic!( + "Received body is not a utf-8 valid string. Raw bytes received: {message_buf:#?}" + ) + }); + let file = + file.unwrap_or_else(|| panic!("Did not receive Uffd from UDS. Received body: {body}")); - let mappings = serde_json::from_str::>(&body) - .expect("Cannot deserialize memory mappings."); + let mappings = + serde_json::from_str::>(&body).unwrap_or_else(|_| { + panic!("Cannot deserialize memory mappings. Received body: {body}") + }); let memsize: usize = mappings.iter().map(|r| r.size).sum(); // Page size is the same for all memory regions, so just grab the first one - let page_size = mappings.first().unwrap().page_size_kib; + let first_mapping = mappings.first().unwrap_or_else(|| { + panic!( + "Cannot get the first mapping. Mappings size is {}. Received body: {body}", + mappings.len() + ) + }); + let page_size = first_mapping.page_size_kib; // Make sure memory size matches backing data size. assert_eq!(memsize, size); From 2b3ec744655e9dae39dd195812787e4bf1a46e69 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 15 Jan 2025 11:40:21 +0000 Subject: [PATCH 176/464] docs: Update documentation on balloon device Add notes around known limitations of the balloon device Signed-off-by: Jack Thomson --- docs/ballooning.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/ballooning.md b/docs/ballooning.md index f5a19271265..f2953d630b5 100644 --- a/docs/ballooning.md +++ b/docs/ballooning.md @@ -263,3 +263,20 @@ cannot be enabled later by providing a `polling_interval` non-zero value. Furthermore, if the balloon was configured with statistics pre-boot through a non-zero `stats_polling_interval_s` value, the statistics cannot be disabled through a `polling_interval` value of zero post-boot. + +## Balloon Caveats + +- Firecracker has no control over the speed of inflation or deflation; this is + dictated by the guest kernel driver. + +- The balloon will continually attempt to reach its target size, which can be a + CPU-intensive process. It is therefore recommended to set realistic targets + or, after a period of stagnation in the inflation, update the target size to + be close to the inflated size. + +- The `deflate_on_oom` flag is a mechanism to prevent the guest from crashing or + terminating processes; it is not meant to be used continually to free memory. + Doing this will be a CPU-intensive process, as the balloon driver is designed + to deflate and release memory slowly. This is also compounded if the balloon + has yet to reach its target size, as it will attempt to inflate while also + deflating. From 994198b0f4fa72837e2521520f21f9103e2803ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 20 Jan 2025 14:25:29 +0100 Subject: [PATCH 177/464] tests: wait for /dev/ptp0 to appear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have sometimes seen that this test can fail. In theory it could happen that udev has not created the /dev/ptp0 file before we run the ssh command. So let's wait in udev for the device to appear up to 5 seconds. Signed-off-by: Pablo Barbáchano --- tests/integration_tests/functional/test_kvm_ptp.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/integration_tests/functional/test_kvm_ptp.py b/tests/integration_tests/functional/test_kvm_ptp.py index 70b5bb877bc..4b44ca124eb 100644 --- a/tests/integration_tests/functional/test_kvm_ptp.py +++ b/tests/integration_tests/functional/test_kvm_ptp.py @@ -6,19 +6,18 @@ import pytest -def test_kvm_ptp(uvm_plain_any): +def test_kvm_ptp(uvm_any_booted): """Test kvm_ptp is usable""" - vm = uvm_plain_any + vm = uvm_any_booted if vm.guest_kernel_version[:2] < (6, 1): pytest.skip("Only supported in kernel 6.1 and after") - vm.spawn() - vm.basic_config(vcpu_count=2, mem_size_mib=256) - vm.add_net_iface() - vm.start() + _, dmesg, _ = vm.ssh.check_output("dmesg |grep -i ptp") + assert "PTP clock support registered" in dmesg - vm.ssh.check_output("[ -c /dev/ptp0 ]") + # wait up to 5s to see the PTP device + vm.ssh.check_output("udevadm wait -t 5 /dev/ptp0") # phc_ctl[14515.127]: clock time is 1697545854.728335694 or Tue Oct 17 12:30:54 2023 vm.ssh.check_output("phc_ctl /dev/ptp0 -- get") From c0a5c517758049d68c3cc084819c5f3605b58643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 30 Oct 2024 16:14:33 +0100 Subject: [PATCH 178/464] tests: make doctests work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./tools/devtool -y test -- --doctest-modules framework Signed-off-by: Pablo Barbáchano --- tests/framework/properties.py | 4 +- tests/framework/utils.py | 4 +- tests/framework/utils_imdsv2.py | 7 ++- tests/host_tools/udp_offload.py | 64 +++++++++++----------- tests/integration_tests/style/test_rust.py | 10 +--- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/tests/framework/properties.py b/tests/framework/properties.py index 7072a2ff3ca..c7c9dfe789d 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 18.04.6 LTS + 'Ubuntu 24.04.1 LTS' """ os_release = Path("/etc/os-release").read_text(encoding="ascii") @@ -41,7 +41,7 @@ def get_host_os(kv: str = None): This only works for AL2 and AL2023 >>> get_host_os("6.1.41-63.118.amzn2023.x86_64") - amzn2023 + 'amzn2023' """ if kv is None: kv = platform.release() diff --git a/tests/framework/utils.py b/tests/framework/utils.py index 8bb1d8c744e..e89b8706651 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -660,8 +660,8 @@ class Timeout: """ A Context Manager to timeout sections of code. - >>> with Timeout(30): - >>> time.sleep(35) + >>> with Timeout(30): # doctest: +SKIP + ... time.sleep(35) # doctest: +SKIP """ def __init__(self, seconds, msg="Timed out"): diff --git a/tests/framework/utils_imdsv2.py b/tests/framework/utils_imdsv2.py index 6420f7f9acf..7a6a89b58a5 100644 --- a/tests/framework/utils_imdsv2.py +++ b/tests/framework/utils_imdsv2.py @@ -24,7 +24,8 @@ class IMDSv2Client: """ A simple IMDSv2 client. - >>> IMDSv2Client().get("/meta-data/instance-type") + >>> IMDSv2Client().get("/meta-data/instance-type") # doctest: +SKIP + ... """ def __init__(self, endpoint="http://169.254.169.254", version="latest"): @@ -49,8 +50,8 @@ def get(self, path): """ Get a metadata path from IMDSv2 - >>> IMDSv2Client().get("/meta-data/instance-type") - >>> m5d.metal + >>> IMDSv2Client().get("/meta-data/instance-type") # doctest: +SKIP + 'm5d.metal' """ headers = {IMDSV2_HDR_TOKEN: self.get_token()} url = f"{self.endpoint}/{self.version}{path}" diff --git a/tests/host_tools/udp_offload.py b/tests/host_tools/udp_offload.py index e9ab6a93966..e105c8e08bd 100644 --- a/tests/host_tools/udp_offload.py +++ b/tests/host_tools/udp_offload.py @@ -24,35 +24,37 @@ def eprint(*args, **kwargs): SOL_UDP = 17 # Protocol number for UDP UDP_SEGMENT = 103 # Option code for UDP segmentation (non-standard) -# Get the IP and port from command-line arguments -if len(sys.argv) != 3: - eprint("Usage: python3 udp_offload.py ") - sys.exit(1) -ip_address = sys.argv[1] -port = int(sys.argv[2]) - -# Create a UDP socket -sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - -# Set the UDP segmentation option (UDP_SEGMENT) to 1400 bytes -OPTVAL = 1400 -try: - sockfd.setsockopt(SOL_UDP, UDP_SEGMENT, OPTVAL) -except (AttributeError, PermissionError): - eprint("Unable to set UDP_SEGMENT option") - sys.exit(1) - -# Set the destination address and port -servaddr = (ip_address, port) - -# Send the message to the destination address -MESSAGE = b"x" -try: - sockfd.sendto(MESSAGE, servaddr) - print("Message sent successfully") -except socket.error as e: - eprint(f"Error sending message: {e}") - sys.exit(1) - -sockfd.close() +if __name__ == "__main__": + # Get the IP and port from command-line arguments + if len(sys.argv) != 3: + eprint("Usage: python3 udp_offload.py ") + sys.exit(1) + + ip_address = sys.argv[1] + port = int(sys.argv[2]) + + # Create a UDP socket + sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + # Set the UDP segmentation option (UDP_SEGMENT) to 1400 bytes + OPTVAL = 1400 + try: + sockfd.setsockopt(SOL_UDP, UDP_SEGMENT, OPTVAL) + except (AttributeError, PermissionError): + eprint("Unable to set UDP_SEGMENT option") + sys.exit(1) + + # Set the destination address and port + servaddr = (ip_address, port) + + # Send the message to the destination address + MESSAGE = b"x" + try: + sockfd.sendto(MESSAGE, servaddr) + print("Message sent successfully") + except socket.error as e: + eprint(f"Error sending message: {e}") + sys.exit(1) + + sockfd.close() diff --git a/tests/integration_tests/style/test_rust.py b/tests/integration_tests/style/test_rust.py index 295f2f209f1..580c33eb03d 100644 --- a/tests/integration_tests/style/test_rust.py +++ b/tests/integration_tests/style/test_rust.py @@ -6,11 +6,7 @@ def test_rust_order(): - """ - Tests that `Cargo.toml` dependencies are alphabetically ordered. - - @type: style - """ + """Tests that `Cargo.toml` dependencies are alphabetically ordered.""" # Runs `cargo-sort` with the current working directory (`cwd`) as the repository root. _, _, _ = utils.check_output( @@ -19,9 +15,7 @@ def test_rust_order(): def test_rust_style(): - """ - Test that rust code passes style checks. - """ + """Test that rust code passes style checks.""" # ../src/io_uring/src/bindings.rs config = open("fmt.toml", encoding="utf-8").read().replace("\n", ",") From 85f1a25815dbcae6e2b518f892db5030093847b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Mon, 20 Jan 2025 19:59:39 +0100 Subject: [PATCH 179/464] tests: rework gitlint_rules.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make doctests and code match. Now running `--doctest-modules` passes the doctests. Simplified the code a bit to make it easier to understand. Signed-off-by: Pablo Barbáchano --- tests/framework/gitlint_rules.py | 130 ++++++++++++++----------------- 1 file changed, 58 insertions(+), 72 deletions(-) diff --git a/tests/framework/gitlint_rules.py b/tests/framework/gitlint_rules.py index fad6ccb47d2..7f38cf11eab 100644 --- a/tests/framework/gitlint_rules.py +++ b/tests/framework/gitlint_rules.py @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 """The user defined rules for gitlint.""" +import re + from gitlint.rules import CommitRule, RuleViolation @@ -22,16 +24,20 @@ class EndsSigned(CommitRule): def validate(self, commit): r"""Validates Signed-off-by and Co-authored-by tags as Linux's scripts/checkpatch.pl - >>> from gitlint.tests.base import BaseTestCase + >>> from gitlint.git import GitContext >>> from gitlint.rules import RuleViolation ... >>> ends_signed = EndsSigned() + >>> miss_sob_follows_coab = "Missing 'Signed-off-by' following 'Co-authored-by'" + >>> miss_sob = "'Signed-off-by' not found in commit message body" + >>> non_sign = "Non 'Co-authored-by' or 'Signed-off-by' string found following 1st 'Signed-off-by'" + >>> email_no_match = "'Co-authored-by' and 'Signed-off-by' name/email do not match" ... >>> msg1 = ( ... f"Title\n\nMessage.\n\n" ... f"Signed-off-by: name " ... ) - >>> commit1 = BaseTestCase.gitcommit(msg1) + >>> commit1 = GitContext.from_commit_msg(msg1).commits[0] >>> ends_signed.validate(commit1) [] >>> msg2 = ( @@ -39,52 +45,41 @@ def validate(self, commit): ... f"Co-authored-by: name \n\n" ... f"Signed-off-by: name " ... ) - >>> commit2 = BaseTestCase.gitcommit(msg2) + >>> commit2 = GitContext.from_commit_msg(msg2).commits[0] >>> ends_signed.validate(commit2) [] - >>> msg3 = ( - ... f"Title\n\nMessage.\n\n" - ... ) - >>> commit3 = BaseTestCase.gitcommit(msg3) + >>> msg3 = f"Title\n\nMessage.\n\n" + >>> commit3 = GitContext.from_commit_msg(msg3).commits[0] >>> vio3 = ends_signed.validate(commit3) - >>> vio_msg3 = ( - ... f"'Signed-off-by:' not found in commit message body" - ... ) - >>> vio3 == [RuleViolation("UC2", vio_msg3)] + >>> vio3 == [RuleViolation("UC2", miss_sob)] True >>> msg4 = ( ... f"Title\n\nMessage.\n\n" ... f"Signed-off-by: name \n\na sentence" ... ) - >>> commit4 = BaseTestCase.gitcommit(msg4) + >>> commit4 = GitContext.from_commit_msg(msg4).commits[0] >>> vio4 = ends_signed.validate(commit4) - >>> vio_msg4 = ( - ... f"Non 'Co-authored-by:' or 'Signed-off-by:' string found following 1st 'Signed-off-by:'" - ... ) - >>> vio4 == [RuleViolation("UC2", vio_msg4, None, 5)] + >>> vio4 == [RuleViolation("UC2", non_sign, None, 6)] True >>> msg5 = ( ... f"Title\n\nMessage.\n\n" ... f"Co-authored-by: name " ... ) - >>> commit5 = BaseTestCase.gitcommit(msg5) + >>> commit5 = GitContext.from_commit_msg(msg5).commits[0] >>> vio5 = ends_signed.validate(commit5) - >>> vio_msg5 = ( - ... f"Missing 'Signed-off-by:' following 'Co-authored-by:'" - ... ) - >>> vio5 == [RuleViolation("UC2", vio_msg5, None, 2)] + >>> vio5 == [ + ... RuleViolation("UC2", miss_sob, None, None), + ... RuleViolation("UC2", miss_sob_follows_coab, None, 5) + ... ] True >>> msg6 = ( ... f"Title\n\nMessage.\n\n" ... f"Co-authored-by: name \n\n" ... f"Signed-off-by: different name " ... ) - >>> commit6 = BaseTestCase.gitcommit(msg6) + >>> commit6 = GitContext.from_commit_msg(msg6).commits[0] >>> vio6 = ends_signed.validate(commit6) - >>> vio_msg6 = ( - ... f"'Co-authored-by:' and 'Signed-off-by:' name/email do not match" - ... ) - >>> vio6 == [RuleViolation("UC2", vio_msg6, None, 6)] + >>> vio6 == [RuleViolation("UC2", email_no_match, None, 6)] True """ @@ -92,59 +87,50 @@ def validate(self, commit): # Utilities def vln(stmt, i): - return RuleViolation(self.id, stmt, None, i) - - co_auth = "Co-authored-by:" - sig = "Signed-off-by:" + violations.append(RuleViolation(self.id, stmt, None, i)) - message_iter = enumerate(commit.message.original.split("\n")) + coab = "Co-authored-by" + sob = "Signed-off-by" - # Skip ahead to the first signoff or co-author tag - - # Checks commit message contains a `Signed-off-by` string - for i, line in message_iter: - if line.startswith(sig) or line.startswith(co_auth): - break - else: - # No signature was found in the message (before `message_iter` ended) - # This check here can have false-negatives (e.g. if the body ends with only - # a 'Co-authored-by' tag), but then below will realize that the co-authored-by - # tag isnt followed by a Signed-off-by tag and fail (and also the DCO check will - # complain). - violations.append(vln(f"'{sig}' not found in commit message body", None)) - - # Check that from here on out we only have signatures and co-authors, and that - # every co-author is immediately followed by a signature with the same name/email. - for i, line in message_iter: - if line.startswith(co_auth): - try: - _, next_line = next(message_iter) - except StopIteration: - violations.append( - vln(f"Missing '{sig}' tag following '{co_auth}'", i) - ) - else: - if not next_line.startswith(sig): - violations.append( - vln(f"Missing '{sig}' tag following '{co_auth}'", i + 1) - ) - continue - - if next_line.split(":")[1].strip() != line.split(":")[1].strip(): - violations.append( - vln(f"{co_auth} and {sig} name/email do not match", i + 1) - ) - continue - - if line.startswith(sig) or not line.strip(): + # find trailers + trailers = [] + for i, line in enumerate(commit.message.original.splitlines()): + # ignore empty lines + if not line: continue + match = re.match(r"([\w-]+):\s+(.*)", line) + if match: + key, val = match.groups() + trailers.append((i, key, val)) + else: + trailers.append((i, "line", line)) + # artificial line so we can check any "previous line" rules + trailers.append((trailers[-1][0] + 1, None, None)) - violations.append( + # Checks commit message contains a `Signed-off-by` string + if not [x for x in trailers if x[1] == sob]: + vln(f"'{sob}' not found in commit message body", None) + + prev_trailer, prev_value = None, None + sig_trailers = False + for i, trailer, value in trailers: + if trailer in {sob, coab}: + sig_trailers = True + elif trailer not in {sob, coab, None} and sig_trailers: vln( - f"Non '{co_auth}' or '{sig}' string found following 1st '{sig}'", + f"Non '{coab}' or '{sob}' string found following 1st '{sob}'", i, ) - ) + # Every co-author is immediately followed by a signature + if prev_trailer == coab: + if trailer != sob: + vln(f"Missing '{sob}' following '{coab}'", i) + else: + # with the same name/email. + if value != prev_value: + vln(f"'{coab}' and '{sob}' name/email do not match", i) + + prev_trailer, prev_value = trailer, value # Return errors return violations From dfb45dc4213bcb1c9704435457e233d3a210dce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 21 Jan 2025 09:45:16 +0100 Subject: [PATCH 180/464] checkstyle: run doctest tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run doctests tests as part of the style step Signed-off-by: Pablo Barbáchano --- tools/devtool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 29434bf8100..768b303e8c5 100755 --- a/tools/devtool +++ b/tools/devtool @@ -934,7 +934,8 @@ cmd_mkdocs() { } cmd_checkstyle() { - cmd_test --no-build --no-kvm-check -- integration_tests/style -n 4 --dist worksteal + cmd_test --no-build --no-kvm-check -- -n 4 --dist worksteal integration_tests/style + cmd_test --no-build --no-kvm-check -- -n 4 --doctest-modules framework } # Check if able to run firecracker. From bcf44d6820f64b62927d4bbf6228dc4effdb6c0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:30:15 +0000 Subject: [PATCH 181/464] build(deps): Bump the firecracker group with 15 updates Bumps the firecracker group with 15 updates: | Package | From | To | | --- | --- | --- | | [uuid](https://github.com/uuid-rs/uuid) | `1.11.1` | `1.12.0` | | [serde_json](https://github.com/serde-rs/json) | `1.0.135` | `1.0.137` | | [micro_http](https://github.com/firecracker-microvm/micro-http) | ``8182cd5`` | ``ef96f62`` | | [log](https://github.com/rust-lang/log) | `0.4.22` | `0.4.25` | | [semver](https://github.com/dtolnay/semver) | `1.0.24` | `1.0.25` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.12.0` | `1.12.1` | | [bitflags](https://github.com/bitflags/bitflags) | `2.7.0` | `2.8.0` | | [kvm-bindings](https://github.com/rust-vmm/kvm) | `0.10.0` | `0.11.0` | | [kvm-ioctls](https://github.com/rust-vmm/kvm) | `0.19.1` | `0.20.0` | | [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.6` | `3.0.7` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.13.0` | `0.13.1` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.24.1` | `0.25.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.9` | `1.2.10` | | [indexmap](https://github.com/indexmap-rs/indexmap) | `2.7.0` | `2.7.1` | | [uuid-macro-internal](https://github.com/uuid-rs/uuid) | `1.11.1` | `1.12.0` | Updates `uuid` from 1.11.1 to 1.12.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.11.1...1.12.0) Updates `serde_json` from 1.0.135 to 1.0.137 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.135...v1.0.137) Updates `micro_http` from `8182cd5` to `ef96f62` - [Commits](https://github.com/firecracker-microvm/micro-http/compare/8182cd5523b63ceb52ad9d0e7eb6fb95683e6d1b...ef96f623c46e221ebf9b6037567f97ec57683afd) Updates `log` from 0.4.22 to 0.4.25 - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.22...0.4.25) Updates `semver` from 1.0.24 to 1.0.25 - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.24...1.0.25) Updates `aws-lc-rs` from 1.12.0 to 1.12.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.12.0...v1.12.1) Updates `bitflags` from 2.7.0 to 2.8.0 - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitflags/bitflags/compare/2.7.0...2.8.0) Updates `kvm-bindings` from 0.10.0 to 0.11.0 - [Release notes](https://github.com/rust-vmm/kvm/releases) - [Changelog](https://github.com/rust-vmm/kvm/blob/v0.11.0/CHANGELOG.md) - [Commits](https://github.com/rust-vmm/kvm/compare/v0.10.0...v0.11.0) Updates `kvm-ioctls` from 0.19.1 to 0.20.0 - [Release notes](https://github.com/rust-vmm/kvm/releases) - [Commits](https://github.com/rust-vmm/kvm/commits) Updates `anstyle-wincon` from 3.0.6 to 3.0.7 - [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.6...anstyle-wincon-v3.0.7) Updates `aws-lc-fips-sys` from 0.13.0 to 0.13.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.0...aws-lc-fips-sys/v0.13.1) Updates `aws-lc-sys` from 0.24.1 to 0.25.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.24.1...aws-lc-sys/v0.25.0) Updates `cc` from 1.2.9 to 1.2.10 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.9...cc-v1.2.10) Updates `indexmap` from 2.7.0 to 2.7.1 - [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md) - [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.0...2.7.1) Updates `uuid-macro-internal` from 1.11.1 to 1.12.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.11.1...1.12.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: micro_http dependency-type: direct:production dependency-group: firecracker - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: bitflags dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: kvm-bindings dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: kvm-ioctls dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: anstyle-wincon dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: indexmap dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 86 +++++++++++++++--------------- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 4 +- src/log-instrument/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/vmm/Cargo.toml | 14 ++--- 8 files changed, 57 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e9a4972b07..6199774c573 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,11 +103,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -125,25 +126,24 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59057b878509d88952425fe694a2806e468612bde2d71943f3cd8034935b5032" +checksum = "f8c7557f6c81ecd3e38582996b31a0f329900586abaae5f092e756686958f22c" dependencies = [ "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", - "libc", "paste", "regex", ] [[package]] name = "aws-lc-rs" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" +checksum = "1ea835662a0af02443aa1396d39be523bbf8f11ee6fad20329607c480bea48c3" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923ded50f602b3007e5e63e3f094c479d9c8a9b42d7f4034e4afe456aa48bfd2" +checksum = "71b2ddd3ada61a305e1d8bb6c005d1eaa7d14d903681edfc400406d523a9b491" dependencies = [ "bindgen 0.69.5", "cc", @@ -187,7 +187,7 @@ version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cexpr", "clang-sys", "lazy_static", @@ -207,7 +207,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cexpr", "clang-sys", "itertools 0.10.5", @@ -232,9 +232,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "byteorder" @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.9" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "jobserver", "libc", @@ -584,7 +584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -632,7 +632,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31c683a9f13de31432e6097131d5f385898c7f0635c0f392b9d0fa165063c8ac" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cfg-if", "log", "managed", @@ -732,9 +732,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -813,9 +813,9 @@ dependencies = [ [[package]] name = "kvm-bindings" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4933174d0cc4b77b958578cd45784071cc5ae212c2d78fbd755aaaa6dfa71a" +checksum = "501bc0717c6a9fc409f29047ebeb6040a4d304344698abb268c4c6a440e6a09a" dependencies = [ "serde", "vmm-sys-util", @@ -824,11 +824,11 @@ dependencies = [ [[package]] name = "kvm-ioctls" -version = "0.19.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e013ae7fcd2c6a8f384104d16afe7ea02969301ea2bb2a56e44b011ebc907cab" +checksum = "3f9120f23310f01dd7b4fbb4ae1fd4eae3e09a7aa5b77038b08a6b37099d8ef4" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "kvm-bindings", "libc", "vmm-sys-util", @@ -879,9 +879,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" dependencies = [ "serde", ] @@ -928,7 +928,7 @@ dependencies = [ [[package]] name = "micro_http" version = "0.1.0" -source = "git+https://github.com/firecracker-microvm/micro-http#8182cd5523b63ceb52ad9d0e7eb6fb95683e6d1b" +source = "git+https://github.com/firecracker-microvm/micro-http#ef96f623c46e221ebf9b6037567f97ec57683afd" dependencies = [ "libc", "vmm-sys-util", @@ -946,7 +946,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cfg-if", "libc", ] @@ -1046,7 +1046,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "lazy_static", "num-traits", "rand", @@ -1157,11 +1157,11 @@ version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1195,9 +1195,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" dependencies = [ "serde", ] @@ -1224,9 +1224,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ "itoa", "memchr", @@ -1436,7 +1436,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d8b176d4d3e420685e964f87c25df5fdd5b26d7eb0d0e7c892d771f5b81035" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cfg-if", "libc", "nix", @@ -1473,9 +1473,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" dependencies = [ "getrandom", "rand", @@ -1484,9 +1484,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91084647266237a48351d05d55dee65bba9e1b597f555fcf54680f820284a1c" +checksum = "144b419c512fdd5eaa4c2998813e32aaab2b257746ee038de93985a99635501d" dependencies = [ "proc-macro2", "quote", @@ -1505,7 +1505,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bce0aad4d8776cb64f1ac591e908a561c50ba6adac4416296efee590b155623f" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "libc", "uuid", "vm-memory", @@ -1555,7 +1555,7 @@ dependencies = [ "aws-lc-rs", "base64", "bincode", - "bitflags 2.7.0", + "bitflags 2.8.0", "crc64", "criterion", "derive_more", @@ -1653,7 +1653,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 0594fc3e349..489a77bb918 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -18,7 +18,7 @@ syn = { version = "2.0.96", features = ["full", "extra-traits", "visit", "visit- walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.11.1", features = ["v4"] } +uuid = { version = "1.12.0", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 6ff36523398..07ac4c310ba 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -15,7 +15,7 @@ displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.135" +serde_json = "1.0.137" thiserror = "2.0.11" vmm = { path = "../vmm" } diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index e6af962ea20..cdb89d174d3 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -24,7 +24,7 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } serde = { version = "1.0.217", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.135" +serde_json = "1.0.137" thiserror = "2.0.11" timerfd = "1.6.0" utils = { path = "../utils" } @@ -43,7 +43,7 @@ userfaultfd = "0.8.1" [build-dependencies] seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217" } -serde_json = "1.0.135" +serde_json = "1.0.137" [features] tracing = ["log-instrument", "utils/tracing", "vmm/tracing"] diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index d9ea9d7dd63..ef5ffde6d7d 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -28,7 +28,7 @@ name = "five" name = "six" [dependencies] -log = "0.4.22" +log = "0.4.25" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 9fd2c3c12ff..50b816a55d0 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -21,7 +21,7 @@ clap = { version = "4.5.23", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.135" +serde_json = "1.0.137" thiserror = "2.0.11" zerocopy = { version = "0.8.14" } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index a9bd3143b86..7aaa0176142 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -16,7 +16,7 @@ displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } -semver = "1.0.24" +semver = "1.0.25" thiserror = "2.0.11" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 4e1cf8eed73..891b19aac40 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,28 +12,28 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.12.0", features = ["bindgen"] } +aws-lc-rs = { version = "1.12.1", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" -bitflags = "2.7.0" +bitflags = "2.8.0" crc64 = "2.0.0" derive_more = { version = "1.0.0", default-features = false, features = ["from", "display"] } displaydoc = "0.2.5" event-manager = "0.4.0" gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } -kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] } -kvm-ioctls = "0.19.1" +kvm-bindings = { version = "0.11.0", features = ["fam-wrappers", "serde"] } +kvm-ioctls = "0.20.0" libc = "0.2.169" linux-loader = "0.13.0" -log = { version = "0.4.22", features = ["std", "serde"] } +log = { version = "0.4.25", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -semver = { version = "1.0.24", features = ["serde"] } +semver = { version = "1.0.25", features = ["serde"] } serde = { version = "1.0.217", features = ["derive", "rc"] } -serde_json = "1.0.135" +serde_json = "1.0.137" slab = "0.4.7" thiserror = "2.0.11" timerfd = "1.5.0" From 38630d23bb9c0857be0acde51cd070f1bef8d241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Tue, 21 Jan 2025 11:46:32 +0100 Subject: [PATCH 182/464] devctr: workaround build failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this is the 3rd time we have issues with git unsafe directories, just assume all directories are safe. This is acceptable since we control all our git dependencies. Signed-off-by: Pablo Barbáchano --- tools/devctr/ctr_gitconfig | 3 +-- tools/devtool | 3 ++- tools/release.sh | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/devctr/ctr_gitconfig b/tools/devctr/ctr_gitconfig index 2ebfb9fcb08..937cb21a308 100644 --- a/tools/devctr/ctr_gitconfig +++ b/tools/devctr/ctr_gitconfig @@ -6,5 +6,4 @@ # https://github.blog/2022-04-12-git-security-vulnerability-announced/ [safe] - directory = /firecracker - directory = /firecracker/.git + directory = * diff --git a/tools/devtool b/tools/devtool index 768b303e8c5..e12048cdb23 100755 --- a/tools/devtool +++ b/tools/devtool @@ -528,10 +528,11 @@ cmd_build() { function cmd_make_release { ensure_build_dir run_devctr \ - --user "$(id -u):$(id -g)" \ + --privileged \ --workdir "$CTR_FC_ROOT_DIR" \ -- \ ./tools/release.sh --libc musl --profile release --make-release + sudo chown -Rc $USER: release* } cmd_distclean() { diff --git a/tools/release.sh b/tools/release.sh index 53d23366793..cb433256932 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -99,6 +99,9 @@ EOF done +# workaround until we rebuild devctr +git config --global --replace-all safe.directory '*' + ARCH=$(uname -m) VERSION=$(get-firecracker-version) PROFILE_DIR=$(get-profile-dir "$PROFILE") From 11b12fa6ca9b2f38a3025461fd826063def89cca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:35:26 +0000 Subject: [PATCH 183/464] build(deps): Bump the firecracker group across 1 directory with 8 updates Bumps the firecracker group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [clap](https://github.com/clap-rs/clap) | `4.5.26` | `4.5.27` | | [uuid](https://github.com/uuid-rs/uuid) | `1.12.0` | `1.12.1` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.12.1` | `1.12.2` | | [is-terminal](https://github.com/sunfishcode/is-terminal) | `0.4.13` | `0.4.14` | | [rustix](https://github.com/bytecodealliance/rustix) | `0.38.43` | `0.38.44` | Updates `clap` from 4.5.26 to 4.5.27 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.26...clap_complete-v4.5.27) Updates `uuid` from 1.12.0 to 1.12.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.12.0...1.12.1) Updates `aws-lc-rs` from 1.12.1 to 1.12.2 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.12.1...v1.12.2) Updates `clap_builder` from 4.5.26 to 4.5.27 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.26...v4.5.27) Updates `is-terminal` from 0.4.13 to 0.4.14 - [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.13...v0.4.14) Updates `rustix` from 0.38.43 to 0.38.44 - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.43...v0.38.44) Updates `uuid-macro-internal` from 1.12.0 to 1.12.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.12.0...1.12.1) Updates `windows-sys` from 0.52.0 to 0.59.0 - [Release notes](https://github.com/microsoft/windows-rs/releases) - [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.59.0) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: is-terminal dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: rustix dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: windows-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 51 ++++++++++++------------------ src/clippy-tracing/Cargo.toml | 4 +-- src/cpu-template-helper/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6199774c573..af8793376bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,7 +98,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -109,7 +109,7 @@ checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", "once_cell", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea835662a0af02443aa1396d39be523bbf8f11ee6fad20329607c480bea48c3" +checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -584,7 +584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -721,7 +721,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -751,13 +751,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "3f187290c0ed3dfe3f7c85bedddd320949b68fc86ca0ceb71adfb05b3dc3af2a" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1153,15 +1153,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1473,9 +1473,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" dependencies = [ "getrandom", "rand", @@ -1484,9 +1484,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144b419c512fdd5eaa4c2998813e32aaab2b257746ee038de93985a99635501d" +checksum = "f8a86d88347b61a0e17b9908a67efcc594130830bf1045653784358dd023e294" dependencies = [ "proc-macro2", "quote", @@ -1653,7 +1653,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1662,15 +1662,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.59.0" diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 489a77bb918..4539472c68f 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.26", features = ["derive"] } +clap = { version = "4.5.27", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" @@ -18,7 +18,7 @@ syn = { version = "2.0.96", features = ["full", "extra-traits", "visit", "visit- walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.12.0", features = ["v4"] } +uuid = { version = "1.12.1", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 07ac4c310ba..ad6d370aafc 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,7 +10,7 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.26", features = ["derive", "string"] } +clap = { version = "4.5.27", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 50b816a55d0..86c8f2e4177 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,7 +17,7 @@ bench = false [dependencies] bincode = "1.2.1" -clap = { version = "4.5.23", features = ["derive", "string"] } +clap = { version = "4.5.27", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" serde = { version = "1.0.217", features = ["derive"] } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 7aaa0176142..c03acf7d535 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,7 +10,7 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.26", features = ["derive", "string"] } +clap = { version = "4.5.27", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 891b19aac40..4bbb146ca18 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.12.1", features = ["bindgen"] } +aws-lc-rs = { version = "1.12.2", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.8.0" From 02b890950ace7ce3d80e597e60ac5e9813b1e356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Wed, 22 Jan 2025 14:51:01 +0100 Subject: [PATCH 184/464] fix: make style checks fail if either test fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since `devtool` does not have `-e`, commands fail but don't fail the test run. Fixes: dfb45dc4213bcb1c9704435457e233d3a210dce2 Signed-off-by: Pablo Barbáchano --- tools/devtool | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/devtool b/tools/devtool index e12048cdb23..1e53cc6c6bb 100755 --- a/tools/devtool +++ b/tools/devtool @@ -935,8 +935,8 @@ cmd_mkdocs() { } cmd_checkstyle() { - cmd_test --no-build --no-kvm-check -- -n 4 --dist worksteal integration_tests/style - cmd_test --no-build --no-kvm-check -- -n 4 --doctest-modules framework + cmd_test --no-build --no-kvm-check -- -n 4 --dist worksteal integration_tests/style || exit 1 + cmd_test --no-build --no-kvm-check -- -n 4 --doctest-modules framework || exit 1 } # Check if able to run firecracker. From ddc2c2aa91d2e0af205c22fd0e94cac0f3fc5032 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 20 Jan 2025 12:27:06 +0000 Subject: [PATCH 185/464] doc: remove devpreview notice from hugepages docs We have decided to move hugepages support out of developer preview, despite missing support for memory ballooning. Signed-off-by: Patrick Roy --- docs/hugepages.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/hugepages.md b/docs/hugepages.md index 05b4e25b399..9102a534c09 100644 --- a/docs/hugepages.md +++ b/docs/hugepages.md @@ -1,10 +1,5 @@ # Backing Guest Memory by Huge Pages -> [!WARNING] -> -> Support is currently in **developer preview**. See -> [this section](RELEASE_POLICY.md#developer-preview-features) for more info. - Firecracker supports backing the guest memory of a VM by 2MB hugetlbfs pages. This can be enabled by setting the `huge_pages` field of `PUT` or `PATCH` requests to the `/machine-config` endpoint to `2M`. From 9054afc9758bcbbad7633980e0db971cd51fa6b7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 20 Jan 2025 12:28:51 +0000 Subject: [PATCH 186/464] remove devpreview log message for hugepages they are no longer in devpreview Signed-off-by: Patrick Roy --- src/vmm/src/resources.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index d0c80789681..d4f89e3423b 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use crate::cpu_config::templates::CustomCpuTemplate; use crate::device_manager::persist::SharedDeviceType; -use crate::logger::{info, log_dev_preview_warning}; +use crate::logger::info; use crate::mmds; use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; @@ -246,10 +246,6 @@ impl VmResources { &mut self, update: &MachineConfigUpdate, ) -> Result<(), MachineConfigError> { - if update.huge_pages.is_some() && update.huge_pages != Some(HugePageConfig::None) { - log_dev_preview_warning("Huge pages support", None); - } - let updated = self.machine_config.update(update)?; // The VM cannot have a memory size smaller than the target size From acf806dcfbfa33dd84be1c03dcf5e7771f855ca9 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 20 Jan 2025 12:46:36 +0000 Subject: [PATCH 187/464] allow combination of initrd and hugepages After simply giving it a try, it seems that this combination of features actually works. So remove all the error branches that disallow it, and update the negative test into a positive test. Signed-off-by: Patrick Roy --- docs/hugepages.md | 1 - src/vmm/src/resources.rs | 13 ------ src/vmm/src/vmm_config/boot_source.rs | 2 - src/vmm/src/vmm_config/machine_config.rs | 2 - .../performance/test_huge_pages.py | 41 +++++++------------ 5 files changed, 14 insertions(+), 45 deletions(-) diff --git a/docs/hugepages.md b/docs/hugepages.md index 9102a534c09..a6f18e06dd2 100644 --- a/docs/hugepages.md +++ b/docs/hugepages.md @@ -39,7 +39,6 @@ Currently, hugetlbfs support is mutually exclusive with the following Firecracker features: - Memory Ballooning via the [Balloon Device](./ballooning.md) -- Initrd ## FAQ diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index d4f89e3423b..2928a22c6ca 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -264,13 +264,6 @@ impl VmResources { if self.balloon.get().is_some() && updated.huge_pages != HugePageConfig::None { return Err(MachineConfigError::BalloonAndHugePages); } - - if self.boot_source.config.initrd_path.is_some() - && updated.huge_pages != HugePageConfig::None - { - return Err(MachineConfigError::InitrdAndHugePages); - } - self.machine_config = updated; Ok(()) @@ -337,12 +330,6 @@ impl VmResources { &mut self, boot_source_cfg: BootSourceConfig, ) -> Result<(), BootSourceConfigError> { - if boot_source_cfg.initrd_path.is_some() - && self.machine_config.huge_pages != HugePageConfig::None - { - return Err(BootSourceConfigError::HugePagesAndInitRd); - } - self.boot_source = BootSource { builder: Some(BootConfig::new(&boot_source_cfg)?), config: boot_source_cfg, diff --git a/src/vmm/src/vmm_config/boot_source.rs b/src/vmm/src/vmm_config/boot_source.rs index 1bfed7bad9c..d62338fc94b 100644 --- a/src/vmm/src/vmm_config/boot_source.rs +++ b/src/vmm/src/vmm_config/boot_source.rs @@ -42,8 +42,6 @@ pub enum BootSourceConfigError { InvalidInitrdPath(io::Error), /// The kernel command line is invalid: {0} InvalidKernelCommandLine(String), - /// Firecracker's huge pages support is incompatible with initrds. - HugePagesAndInitRd, } /// Holds the kernel specification (both configuration as well as runtime details). diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 092179f5ff5..0a140ea890b 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -31,8 +31,6 @@ pub enum MachineConfigError { KernelVersion, /// Firecracker's huge pages support is incompatible with memory ballooning. BalloonAndHugePages, - /// Firecracker's huge pages support is incompatible with initrds. - InitrdAndHugePages, } /// Describes the possible (huge)page configurations for a microVM's memory. diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 8437d78c7d3..2aa45160836 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -7,9 +7,10 @@ import pytest from framework import utils -from framework.microvm import HugePagesConfig +from framework.microvm import HugePagesConfig, Serial from framework.properties import global_props from framework.utils_ftrace import ftrace_events +from integration_tests.functional.test_initrd import INITRD_FILESYSTEM from integration_tests.functional.test_uffd import SOCKET_PATH, spawn_pf_handler @@ -259,33 +260,19 @@ def test_negative_huge_pages_plus_initrd(uvm_with_initrd): uvm_with_initrd.spawn() uvm_with_initrd.memory_monitor = None - # Ensure setting huge pages and then telling FC to boot an initrd does not work - with pytest.raises( - RuntimeError, - match="Boot source error: Firecracker's huge pages support is incompatible with initrds.", - ): - # `basic_config` first does a PUT to /machine-config, which will apply the huge pages configuration, - # and then a PUT to /boot-source, which will register the initrd - uvm_with_initrd.basic_config( - boot_args="console=ttyS0 reboot=k panic=1 pci=off", - use_initrd=True, - huge_pages=HugePagesConfig.HUGETLBFS_2MB, - add_root_device=False, - vcpu_count=1, - ) - - # Ensure telling FC about the initrd first and then setting huge pages doesn't work - # This first does a PUT to /machine-config to reset the huge pages configuration, before doing a - # PUT to /boot-source to register the initrd + # `basic_config` first does a PUT to /machine-config, which will apply the huge pages configuration, + # and then a PUT to /boot-source, which will register the initrd uvm_with_initrd.basic_config( - huge_pages=HugePagesConfig.NONE, boot_args="console=ttyS0 reboot=k panic=1 pci=off", use_initrd=True, + huge_pages=HugePagesConfig.HUGETLBFS_2MB, + add_root_device=False, + vcpu_count=1, ) - with pytest.raises( - RuntimeError, - match="Machine config error: Firecracker's huge pages support is incompatible with initrds.", - ): - uvm_with_initrd.api.machine_config.patch( - huge_pages=HugePagesConfig.HUGETLBFS_2MB - ) + + uvm_with_initrd.start() + serial = Serial(uvm_with_initrd) + serial.open() + serial.rx(token="# ") + serial.tx("mount |grep rootfs") + serial.rx(token=f"rootfs on / type {INITRD_FILESYSTEM}") From aeb17549873d70eb3d852174b07f2cf8b6593d3a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 20 Jan 2025 12:55:44 +0000 Subject: [PATCH 188/464] test: generalize initrd test Run it with all supported guest kernels, and handle the huge page configuration via pytest parametrization, so that we do not have the same test twice. Signed-off-by: Patrick Roy --- tests/conftest.py | 14 ---------- .../performance/test_huge_pages.py | 27 +------------------ .../test_initrd.py | 19 +++++++++++-- 3 files changed, 18 insertions(+), 42 deletions(-) rename tests/integration_tests/{functional => performance}/test_initrd.py (56%) diff --git a/tests/conftest.py b/tests/conftest.py index 8c81714f716..41e0fbf2721 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -498,20 +498,6 @@ def uvm_plain_debug(microvm_factory, guest_kernel_6_1_debug, rootfs_rw): return microvm_factory.build(guest_kernel_6_1_debug, rootfs_rw) -@pytest.fixture -def uvm_with_initrd( - microvm_factory, guest_kernel_linux_5_10, record_property, artifact_dir -): - """ - See file:../docs/initrd.md - """ - fs = artifact_dir / "initramfs.cpio" - record_property("rootfs", fs.name) - uvm = microvm_factory.build(guest_kernel_linux_5_10) - uvm.initrd_file = fs - yield uvm - - @pytest.fixture def vcpu_count(): """Return default vcpu_count. Use indirect parametrization to override.""" diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 2aa45160836..51b5dd57418 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -7,10 +7,9 @@ import pytest from framework import utils -from framework.microvm import HugePagesConfig, Serial +from framework.microvm import HugePagesConfig from framework.properties import global_props from framework.utils_ftrace import ftrace_events -from integration_tests.functional.test_initrd import INITRD_FILESYSTEM from integration_tests.functional.test_uffd import SOCKET_PATH, spawn_pf_handler @@ -252,27 +251,3 @@ def test_negative_huge_pages_plus_balloon(uvm_plain): match="Machine config error: Firecracker's huge pages support is incompatible with memory ballooning.", ): uvm_plain.basic_config(huge_pages=HugePagesConfig.HUGETLBFS_2MB) - - -def test_negative_huge_pages_plus_initrd(uvm_with_initrd): - """Tests that huge pages and initrd cannot be used together""" - uvm_with_initrd.jailer.daemonize = False - uvm_with_initrd.spawn() - uvm_with_initrd.memory_monitor = None - - # `basic_config` first does a PUT to /machine-config, which will apply the huge pages configuration, - # and then a PUT to /boot-source, which will register the initrd - uvm_with_initrd.basic_config( - boot_args="console=ttyS0 reboot=k panic=1 pci=off", - use_initrd=True, - huge_pages=HugePagesConfig.HUGETLBFS_2MB, - add_root_device=False, - vcpu_count=1, - ) - - uvm_with_initrd.start() - serial = Serial(uvm_with_initrd) - serial.open() - serial.rx(token="# ") - serial.tx("mount |grep rootfs") - serial.rx(token=f"rootfs on / type {INITRD_FILESYSTEM}") diff --git a/tests/integration_tests/functional/test_initrd.py b/tests/integration_tests/performance/test_initrd.py similarity index 56% rename from tests/integration_tests/functional/test_initrd.py rename to tests/integration_tests/performance/test_initrd.py index 3c48ecd63a5..3845e5610c0 100644 --- a/tests/integration_tests/functional/test_initrd.py +++ b/tests/integration_tests/performance/test_initrd.py @@ -1,13 +1,27 @@ # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """Tests for initrd.""" +import pytest -from framework.microvm import Serial +from framework.microvm import HugePagesConfig, Serial INITRD_FILESYSTEM = "rootfs" -def test_microvm_initrd_with_serial(uvm_with_initrd): +@pytest.fixture +def uvm_with_initrd(microvm_factory, guest_kernel, record_property, artifact_dir): + """ + See file:../docs/initrd.md + """ + fs = artifact_dir / "initramfs.cpio" + record_property("rootfs", fs.name) + uvm = microvm_factory.build(guest_kernel) + uvm.initrd_file = fs + yield uvm + + +@pytest.mark.parametrize("huge_pages", HugePagesConfig) +def test_microvm_initrd_with_serial(uvm_with_initrd, huge_pages): """ Test that a boot using initrd successfully loads the root filesystem. """ @@ -21,6 +35,7 @@ def test_microvm_initrd_with_serial(uvm_with_initrd): vcpu_count=1, boot_args="console=ttyS0 reboot=k panic=1 pci=off", use_initrd=True, + huge_pages=huge_pages, ) vm.start() From d28ef60fdd59570a61498c4e218498dc72643d00 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 20 Jan 2025 06:44:57 +0000 Subject: [PATCH 189/464] fix: clarify comments in kani module QUEUE_END is the address of the first byte past the end of our queue indeed, but the queue doesnt start at 0 (it starts at QUEUE_BASE_ADDRESS, which is 512), and thus GUEST_MEMORY_SIZE was 512 byte too large, because it assumed QUEUE_END was also the size of the queue. Closes #4997 Reported-by: Matias Ezequiel Vara Larsen Signed-off-by: Patrick Roy --- src/vmm/src/devices/virtio/queue.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs index 7f595d7d9f7..d84c4988d62 100644 --- a/src/vmm/src/devices/virtio/queue.rs +++ b/src/vmm/src/devices/virtio/queue.rs @@ -803,10 +803,11 @@ mod verification { const GUEST_MEMORY_BASE: u64 = 512; // We size our guest memory to fit a properly aligned queue, plus some wiggles bytes - // to make sure we not only test queues where all segments are consecutively aligned. + // to make sure we not only test queues where all segments are consecutively aligned (at least + // for those proofs that use a completely arbitrary queue structure). // We need to give at least 16 bytes of buffer space for the descriptor table to be // able to change its address, as it is 16-byte aligned. - const GUEST_MEMORY_SIZE: usize = QUEUE_END as usize + 30; + const GUEST_MEMORY_SIZE: usize = (QUEUE_END - QUEUE_BASE_ADDRESS) as usize + 30; fn guest_memory(memory: *mut u8) -> ProofGuestMemory { // Ideally, we'd want to do @@ -876,8 +877,7 @@ mod verification { const USED_RING_BASE_ADDRESS: u64 = AVAIL_RING_BASE_ADDRESS + 6 + 2 * FIRECRACKER_MAX_QUEUE_SIZE as u64 + 2; - /// The address of the first byte after the queue. Since our queue starts at guest physical - /// address 0, this is also the size of the memory area occupied by the queue. + /// The address of the first byte after the queue (which starts at QUEUE_BASE_ADDRESS). /// Note that the used ring structure has size 6 + 8 * FIRECRACKER_MAX_QUEUE_SIZE const QUEUE_END: u64 = USED_RING_BASE_ADDRESS + 6 + 8 * FIRECRACKER_MAX_QUEUE_SIZE as u64; From a2a34846616c492deb7fd894720ccdc4607360f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Thu, 23 Jan 2025 09:56:21 +0100 Subject: [PATCH 190/464] test: sync fs before checking for output file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can happen that we check for the file before `socat` has written it in the filesystem. Sync before checking. Signed-off-by: Pablo Barbáchano --- tests/integration_tests/functional/test_net.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py index a01157dcf76..20a40e677b0 100644 --- a/tests/integration_tests/functional/test_net.py +++ b/tests/integration_tests/functional/test_net.py @@ -115,9 +115,8 @@ def test_tap_offload(uvm_any): ) # Try to send a UDP message from host with UDP offload enabled - cmd = f"ip netns exec {vm.ssh.netns} python3 ./host_tools/udp_offload.py {vm.ssh.host} {port}" - utils.check_output(cmd) + vm.netns.check_output(f"python3 ./host_tools/udp_offload.py {vm.ssh.host} {port}") # Check that the server received the message - ret = vm.ssh.run(f"cat {out_filename}") + ret = vm.ssh.run(f"sync ; cat {out_filename}") assert ret.stdout == message, f"{ret.stdout=} {ret.stderr=}" From 88e0b6e5243331801af0b932dc42fdfa0b5853d7 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 22 Jan 2025 12:22:14 +0000 Subject: [PATCH 191/464] Call kvmclock_ctrl on GDB pause When we pause for GDB call `KVM_KVMCLOCK_CTRL` to prevent guest softlockup watchdog panic. Signed-off-by: Jack Thomson --- CHANGELOG.md | 3 +++ src/vmm/src/vstate/vcpu/mod.rs | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00e82ee4b19..d6a8e1b2ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ and this project adheres to `mem_size_mib` and `track_dirty_pages` being mandatory for all `PATCH /machine-config` requests. Now, they can be omitted which leaves these parts of the machine configuration unchanged. +- [#5007](https://github.com/firecracker-microvm/firecracker/pull/5007): Fixed + watchdog softlockup warning on x86_64 guests when a vCPU is paused during GDB + debugging. ## [1.10.1] diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 6a6471193dc..d9aa0abd1a8 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -319,6 +319,16 @@ impl Vcpu { // If the emulation requests a pause lets do this #[cfg(feature = "gdb")] Ok(VcpuEmulation::Paused) => { + // Calling `KVM_KVMCLOCK_CTRL` to make sure the guest softlockup watchdog + // does not panic on resume, see https://docs.kernel.org/virt/kvm/api.html . + // We do not want to fail if the call is not successful, because depending + // that may be acceptable depending on the workload. + #[cfg(target_arch = "x86_64")] + if let Err(err) = self.kvm_vcpu.fd.kvmclock_ctrl() { + METRICS.vcpu.kvmclock_ctrl_fails.inc(); + warn!("KVM_KVMCLOCK_CTRL call failed {}", err); + } + return StateMachine::next(Self::paused); } // Emulation errors lead to vCPU exit. From 4b6c9b3de864bd88c2755925cb47c89f2bf4c13c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 16:50:48 +0000 Subject: [PATCH 192/464] build(deps): Bump the firecracker group with 6 updates Bumps the firecracker group with 6 updates: | Package | From | To | | --- | --- | --- | | [clap-num](https://github.com/newAM/clap-num) | `1.1.1` | `1.2.0` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.13.1` | `0.13.2` | | [cpufeatures](https://github.com/RustCrypto/utils) | `0.2.16` | `0.2.17` | | [crunchy](https://github.com/eira-fransham/crunchy) | `0.2.2` | `0.2.3` | | [is-terminal](https://github.com/sunfishcode/is-terminal) | `0.4.14` | `0.4.15` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.14` | `1.0.15` | Updates `clap-num` from 1.1.1 to 1.2.0 - [Release notes](https://github.com/newAM/clap-num/releases) - [Changelog](https://github.com/newAM/clap-num/blob/main/CHANGELOG.md) - [Commits](https://github.com/newAM/clap-num/compare/1.1.1...1.2.0) Updates `aws-lc-fips-sys` from 0.13.1 to 0.13.2 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.1...aws-lc-fips-sys/v0.13.2) Updates `cpufeatures` from 0.2.16 to 0.2.17 - [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.16...cpufeatures-v0.2.17) Updates `crunchy` from 0.2.2 to 0.2.3 - [Commits](https://github.com/eira-fransham/crunchy/commits) Updates `is-terminal` from 0.4.14 to 0.4.15 - [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.14...v0.4.15) Updates `unicode-ident` from 1.0.14 to 1.0.15 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.14...1.0.15) --- updated-dependencies: - dependency-name: clap-num dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cpufeatures dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: crunchy dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: is-terminal dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 24 ++++++++++++------------ src/snapshot-editor/Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af8793376bb..de011b07a1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,9 +126,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c7557f6c81ecd3e38582996b31a0f329900586abaae5f092e756686958f22c" +checksum = "33e4aa2478e3ff7e6c2624558abfdad004a57ba975974b4769a4c0d12831f143" dependencies = [ "bindgen 0.69.5", "cc", @@ -344,9 +344,9 @@ dependencies = [ [[package]] name = "clap-num" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e063d263364859dc54fb064cedb7c122740cd4733644b14b176c097f51e8ab7" +checksum = "822c4000301ac390e65995c62207501e3ef800a1fc441df913a5e8e4dc374816" dependencies = [ "num-traits", ] @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -475,9 +475,9 @@ dependencies = [ [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-common" @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f187290c0ed3dfe3f7c85bedddd320949b68fc86ca0ceb71adfb05b3dc3af2a" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" dependencies = [ "hermit-abi", "libc", @@ -1404,9 +1404,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" [[package]] name = "unicode-xid" diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index c03acf7d535..b75f490b7b0 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -22,7 +22,7 @@ vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" [target.'cfg(target_arch = "aarch64")'.dependencies] -clap-num = "1.0.2" +clap-num = "1.2.0" [features] tracing = ["log-instrument", "fc_utils/tracing", "vmm/tracing"] From 0d2713b16212b71dab1a0ec66a3624232bdbb685 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 28 Jan 2025 12:14:04 +0000 Subject: [PATCH 193/464] fix(test): have codecov uploader exit with non-zero code on error Pass the `-Z` flag (fail on error) to the codecov uploader. According to the docs, without this flag upload failures will be silently ignored (why isn't this the default??) [1]. We can also see this from the logs, which contain: ``` [2025-01-28T12:10:57.973Z] ['info'] Codecov will exit with status code 0. If you are expecting a non-zero exit code, please pass in the `-Z` flag ``` The docs say that a long form `--fail-on-error` is available, but actually it doesnt seem to work, so we have to use `-Z`. [1]: https://docs.codecov.com/docs/cli-options Signed-off-by: Patrick Roy --- tests/integration_tests/build/test_coverage.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/build/test_coverage.py b/tests/integration_tests/build/test_coverage.py index 9369498b377..9dbd97693f6 100644 --- a/tests/integration_tests/build/test_coverage.py +++ b/tests/integration_tests/build/test_coverage.py @@ -95,7 +95,9 @@ def test_coverage(monkeypatch): if not branch: branch = utils.check_output("git rev-parse --abbrev-ref HEAD").stdout - codecov_cmd = f"codecov -f {lcov_file} -F {global_props.host_linux_version}-{global_props.instance}" + # -Z flag means "fail on error". There's supposed to be a more descriptive long form in + # --fail-on-error, but it doesnt work. + codecov_cmd = f"codecov -Z -f {lcov_file} -F {global_props.host_linux_version}-{global_props.instance}" if pr_number and pr_number != "false": codecov_cmd += f" -P {pr_number}" From bb1edd189acca83b6202cb27e129ab9695611351 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 15:01:15 +0000 Subject: [PATCH 194/464] fix(test): validate restored test works in test_valid_handler In test_valid_handler, we had a comment to validate that the guest still works if we mess with the balloon after UFFD-based restoration. However, we didn't actually do so. Fix this by running some simple SSH command after both inflation and deflation. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_uffd.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index fbb86c4c987..398529de77d 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -118,10 +118,14 @@ def test_valid_handler(uvm_plain, snapshot, uffd_handler_paths): # Inflate balloon. vm.api.balloon.patch(amount_mib=200) + # Verify if the restored guest works. + vm.ssh.check_output("true") + # Deflate balloon. vm.api.balloon.patch(amount_mib=0) # Verify if the restored guest works. + vm.ssh.check_output("true") def test_malicious_handler(uvm_plain, snapshot, uffd_handler_paths): From 9536eaa6247c844aea6194ef5b7e1111431074d9 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 15:18:49 +0000 Subject: [PATCH 195/464] fix: only use mmap trick when restoring from file When the balloon inflates, and the guest gives us back some pages of memory, we need to free those pages. In booted VMs, we do this with madvise(MADV_DONTNEED), and in restored VMs we do it by MAP_FIXED-ing a new VMA on top of the range-to-free. This is because if guest memory is a MAP_PRIVATE of a memory file, madvise has no effect. However, we also do this MAP_FIXED trick if the snapshot is restored with UFFD. In this case, its not needed (madvise works perfectly fine), and in fact, its wrong: If we map over the memory range, UFFD will not receive Remove events for the specified range. Fix this by only using the mmap trick for file-based restored. Fixes #4988 Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 1 + src/vmm/src/device_manager/persist.rs | 7 ++++++- src/vmm/src/devices/virtio/balloon/device.rs | 10 +++++----- src/vmm/src/devices/virtio/balloon/persist.rs | 15 ++++++++++++--- src/vmm/src/devices/virtio/balloon/util.rs | 4 ++-- src/vmm/src/lib.rs | 2 -- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 4b43e67541f..fc23d8add0b 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -531,6 +531,7 @@ pub fn build_microvm_from_snapshot( resource_allocator: &mut vmm.resource_allocator, vm_resources, instance_id: &instance_info.id, + restored_from_file: vmm.uffd.is_none(), }; vmm.mmio_device_manager = diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index 5773fa0ba09..bdf63409d68 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -214,6 +214,7 @@ pub struct MMIODevManagerConstructorArgs<'a> { pub resource_allocator: &'a mut ResourceAllocator, pub vm_resources: &'a mut VmResources, pub instance_id: &'a str, + pub restored_from_file: bool, } impl fmt::Debug for MMIODevManagerConstructorArgs<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -512,7 +513,10 @@ impl<'a> Persist<'a> for MMIODeviceManager { if let Some(balloon_state) = &state.balloon_device { let device = Arc::new(Mutex::new(Balloon::restore( - BalloonConstructorArgs { mem: mem.clone() }, + BalloonConstructorArgs { + mem: mem.clone(), + restored_from_file: constructor_args.restored_from_file, + }, &balloon_state.device_state, )?)); @@ -807,6 +811,7 @@ mod tests { resource_allocator: &mut resource_allocator, vm_resources, instance_id: "microvm-id", + restored_from_file: true, }; let restored_dev_manager = MMIODeviceManager::restore(restore_args, &device_states).unwrap(); diff --git a/src/vmm/src/devices/virtio/balloon/device.rs b/src/vmm/src/devices/virtio/balloon/device.rs index 697928ae9c6..f6be2536de5 100644 --- a/src/vmm/src/devices/virtio/balloon/device.rs +++ b/src/vmm/src/devices/virtio/balloon/device.rs @@ -164,7 +164,7 @@ pub struct Balloon { pub(crate) irq_trigger: IrqTrigger, // Implementation specific fields. - pub(crate) restored: bool, + pub(crate) restored_from_file: bool, pub(crate) stats_polling_interval_s: u16, pub(crate) stats_timer: TimerFd, // The index of the previous stats descriptor is saved because @@ -189,7 +189,7 @@ impl fmt::Debug for Balloon { .field("queue_evts", &self.queue_evts) .field("device_state", &self.device_state) .field("irq_trigger", &self.irq_trigger) - .field("restored", &self.restored) + .field("restored_from_file", &self.restored_from_file) .field("stats_polling_interval_s", &self.stats_polling_interval_s) .field("stats_desc_index", &self.stats_desc_index) .field("latest_stats", &self.latest_stats) @@ -204,7 +204,7 @@ impl Balloon { amount_mib: u32, deflate_on_oom: bool, stats_polling_interval_s: u16, - restored: bool, + restored_from_file: bool, ) -> Result { let mut avail_features = 1u64 << VIRTIO_F_VERSION_1; @@ -245,7 +245,7 @@ impl Balloon { irq_trigger: IrqTrigger::new().map_err(BalloonError::EventFd)?, device_state: DeviceState::Inactive, activate_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(BalloonError::EventFd)?, - restored, + restored_from_file, stats_polling_interval_s, stats_timer, stats_desc_index: None, @@ -355,7 +355,7 @@ impl Balloon { if let Err(err) = remove_range( mem, (guest_addr, u64::from(range_len) << VIRTIO_BALLOON_PFN_SHIFT), - self.restored, + self.restored_from_file, ) { error!("Error removing memory range: {:?}", err); } diff --git a/src/vmm/src/devices/virtio/balloon/persist.rs b/src/vmm/src/devices/virtio/balloon/persist.rs index 4e768ddd2e2..c1fb6865b5f 100644 --- a/src/vmm/src/devices/virtio/balloon/persist.rs +++ b/src/vmm/src/devices/virtio/balloon/persist.rs @@ -95,6 +95,7 @@ pub struct BalloonState { pub struct BalloonConstructorArgs { /// Pointer to guest memory. pub mem: GuestMemoryMmap, + pub restored_from_file: bool, } impl Persist<'_> for Balloon { @@ -121,7 +122,12 @@ impl Persist<'_> for Balloon { ) -> Result { // We can safely create the balloon with arbitrary flags and // num_pages because we will overwrite them after. - let mut balloon = Balloon::new(0, false, state.stats_polling_interval_s, true)?; + let mut balloon = Balloon::new( + 0, + false, + state.stats_polling_interval_s, + constructor_args.restored_from_file, + )?; let mut num_queues = BALLOON_NUM_QUEUES; // As per the virtio 1.1 specification, the statistics queue @@ -192,13 +198,16 @@ mod tests { // Deserialize and restore the balloon device. let restored_balloon = Balloon::restore( - BalloonConstructorArgs { mem: guest_mem }, + BalloonConstructorArgs { + mem: guest_mem, + restored_from_file: true, + }, &Snapshot::deserialize(&mut mem.as_slice()).unwrap(), ) .unwrap(); assert_eq!(restored_balloon.device_type(), TYPE_BALLOON); - assert!(restored_balloon.restored); + assert!(restored_balloon.restored_from_file); assert_eq!(restored_balloon.acked_features, balloon.acked_features); assert_eq!(restored_balloon.avail_features, balloon.avail_features); diff --git a/src/vmm/src/devices/virtio/balloon/util.rs b/src/vmm/src/devices/virtio/balloon/util.rs index f8cf7aa2000..a9960540a60 100644 --- a/src/vmm/src/devices/virtio/balloon/util.rs +++ b/src/vmm/src/devices/virtio/balloon/util.rs @@ -68,7 +68,7 @@ pub(crate) fn compact_page_frame_numbers(v: &mut [u32]) -> Vec<(u32, u32)> { pub(crate) fn remove_range( guest_memory: &GuestMemoryMmap, range: (GuestAddress, u64), - restored: bool, + restored_from_file: bool, ) -> Result<(), RemoveRegionError> { let (guest_address, range_len) = range; @@ -83,7 +83,7 @@ pub(crate) fn remove_range( // Mmap a new anonymous region over the present one in order to create a hole. // This workaround is (only) needed after resuming from a snapshot because the guest memory // is mmaped from file as private and there is no `madvise` flag that works for this case. - if restored { + if restored_from_file { // SAFETY: The address and length are known to be valid. let ret = unsafe { libc::mmap( diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 6833a3a12d2..618f5d7b6c3 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -314,8 +314,6 @@ pub struct Vmm { vm: Vm, guest_memory: GuestMemoryMmap, // Save UFFD in order to keep it open in the Firecracker process, as well. - // Since this field is never read again, we need to allow `dead_code`. - #[allow(dead_code)] uffd: Option, vcpus_handles: Vec, // Used by Vcpus and devices to initiate teardown; Vmm should never write here. From e92a7ff01aa5e298586af48b19a4533980d01b61 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 15:47:02 +0000 Subject: [PATCH 196/464] fix(example): correctly handle `remove` events in uffd exammple The crux of the issue was that UFFD gets blocked (all ioctls return -EAGAIN) when there's any `remove` events pending in the queue, which means during processing we not only need to look at the "head" of the queue, but also make sure there's no `remove` events in the "tail". Deal with these scenarios correctly by always greedily reading the entire queue, to ensure there's nothing pending, and only then processing things one-by-one. Please see the new code comments for intricacies with this approach. Fixes #4990 Signed-off-by: Patrick Roy --- .../examples/uffd/fault_all_handler.rs | 2 +- src/firecracker/examples/uffd/uffd_utils.rs | 43 ++++++--- .../examples/uffd/valid_handler.rs | 89 +++++++++++++++---- 3 files changed, 106 insertions(+), 28 deletions(-) diff --git a/src/firecracker/examples/uffd/fault_all_handler.rs b/src/firecracker/examples/uffd/fault_all_handler.rs index 5e9f49a3207..cfeaa099236 100644 --- a/src/firecracker/examples/uffd/fault_all_handler.rs +++ b/src/firecracker/examples/uffd/fault_all_handler.rs @@ -36,7 +36,7 @@ fn main() { userfaultfd::Event::Pagefault { .. } => { for region in uffd_handler.mem_regions.clone() { uffd_handler - .serve_pf(region.mapping.base_host_virt_addr as _, region.mapping.size) + .serve_pf(region.mapping.base_host_virt_addr as _, region.mapping.size); } } _ => panic!("Unexpected event on userfaultfd"), diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index 8cc70ab7c21..a2f7879f591 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -116,7 +116,7 @@ impl UffdHandler { } } - pub fn serve_pf(&mut self, addr: *mut u8, len: usize) { + pub fn serve_pf(&mut self, addr: *mut u8, len: usize) -> bool { // Find the start of the page that the current faulting address belongs to. let dst = (addr as usize & !(self.page_size - 1)) as *mut libc::c_void; let fault_page_addr = dst as u64; @@ -133,14 +133,18 @@ impl UffdHandler { // event was received. This can be a consequence of guest reclaiming back its // memory from the host (through balloon device) Some(MemPageState::Uninitialized) | Some(MemPageState::FromFile) => { - let (start, end) = self.populate_from_file(region, fault_page_addr, len); - self.update_mem_state_mappings(start, end, MemPageState::FromFile); - return; + match self.populate_from_file(region, fault_page_addr, len) { + Some((start, end)) => { + self.update_mem_state_mappings(start, end, MemPageState::FromFile) + } + None => return false, + } + return true; } Some(MemPageState::Removed) | Some(MemPageState::Anonymous) => { let (start, end) = self.zero_out(fault_page_addr); self.update_mem_state_mappings(start, end, MemPageState::Anonymous); - return; + return true; } None => {} } @@ -152,20 +156,39 @@ impl UffdHandler { ); } - fn populate_from_file(&self, region: &MemRegion, dst: u64, len: usize) -> (u64, u64) { + fn populate_from_file(&self, region: &MemRegion, dst: u64, len: usize) -> Option<(u64, u64)> { let offset = dst - region.mapping.base_host_virt_addr; let src = self.backing_buffer as u64 + region.mapping.offset + offset; let ret = unsafe { - self.uffd - .copy(src as *const _, dst as *mut _, len, true) - .expect("Uffd copy failed") + match self.uffd.copy(src as *const _, dst as *mut _, len, true) { + Ok(value) => value, + // Catch EAGAIN errors, which occur when a `remove` event lands in the UFFD + // queue while we're processing `pagefault` events. + // The weird cast is because the `bytes_copied` field is based on the + // `uffdio_copy->copy` field, which is a signed 64 bit integer, and if something + // goes wrong, it gets set to a -errno code. However, uffd-rs always casts this + // value to an unsigned `usize`, which scrambled the errno. + Err(Error::PartiallyCopied(bytes_copied)) + if bytes_copied == 0 || bytes_copied == (-libc::EAGAIN) as usize => + { + return None + } + Err(Error::CopyFailed(errno)) + if std::io::Error::from(errno).raw_os_error().unwrap() == libc::EEXIST => + { + len + } + Err(e) => { + panic!("Uffd copy failed: {e:?}"); + } + } }; // Make sure the UFFD copied some bytes. assert!(ret > 0); - (dst, dst + len as u64) + Some((dst, dst + len as u64)) } fn zero_out(&mut self, addr: u64) -> (u64, u64) { diff --git a/src/firecracker/examples/uffd/valid_handler.rs b/src/firecracker/examples/uffd/valid_handler.rs index 6c681d932ac..936b9f517a3 100644 --- a/src/firecracker/examples/uffd/valid_handler.rs +++ b/src/firecracker/examples/uffd/valid_handler.rs @@ -26,24 +26,79 @@ fn main() { let mut runtime = Runtime::new(stream, file); runtime.install_panic_hook(); runtime.run(|uffd_handler: &mut UffdHandler| { - // Read an event from the userfaultfd. - let event = uffd_handler - .read_event() - .expect("Failed to read uffd_msg") - .expect("uffd_msg not ready"); - - // We expect to receive either a Page Fault or Removed - // event (if the balloon device is enabled). - match event { - userfaultfd::Event::Pagefault { addr, .. } => { - uffd_handler.serve_pf(addr.cast(), uffd_handler.page_size) + // !DISCLAIMER! + // When using UFFD together with the balloon device, this handler needs to deal with + // `remove` and `pagefault` events. There are multiple things to keep in mind in + // such setups: + // + // As long as any `remove` event is pending in the UFFD queue, all ioctls return EAGAIN + // ----------------------------------------------------------------------------------- + // + // This means we cannot process UFFD events simply one-by-one anymore - if a `remove` event + // arrives, we need to pre-fetch all other events up to the `remove` event, to unblock the + // UFFD, and then go back to the process the pre-fetched events. + // + // UFFD might receive events in not in their causal order + // ----------------------------------------------------- + // + // For example, the guest + // kernel might first respond to a balloon inflation by freeing some memory, and + // telling Firecracker about this. Firecracker will then madvise(MADV_DONTNEED) the + // free memory range, which causes a `remove` event to be sent to UFFD. Then, the + // guest kernel might immediately fault the page in again (for example because + // default_on_oom was set). which causes a `pagefault` event to be sent to UFFD. + // + // However, the pagefault will be triggered from inside KVM on the vCPU thread, while the + // balloon device is handled by Firecracker on its VMM thread. This means that potentially + // this handler can receive the `pagefault` _before_ the `remove` event. + // + // This means that the simple "greedy" strategy of simply prefetching _all_ UFFD events + // to make sure no `remove` event is blocking us can result in the handler acting on + // the `pagefault` event before the `remove` message (despite the `remove` event being + // in the causal past of the `pagefault` event), which means that we will fault in a page + // from the snapshot file, while really we should be faulting in a zero page. + // + // In this example handler, we ignore this problem, to avoid + // complexity (under the assumption that the guest kernel will zero a newly faulted in + // page anyway). A production handler will most likely want to ensure that `remove` + // events for a specific range are always handled before `pagefault` events. + // + // Lastly, we still need to deal with the race condition where a `remove` event arrives + // in the UFFD queue after we got done reading all events, in which case we need to go + // back to reading more events before we can continue processing `pagefault`s. + let mut deferred_events = Vec::new(); + + loop { + // First, try events that we couldn't handle last round + let mut events_to_handle = Vec::from_iter(deferred_events.drain(..)); + + // Read all events from the userfaultfd. + while let Some(event) = uffd_handler.read_event().expect("Failed to read uffd_msg") { + events_to_handle.push(event); + } + + for event in events_to_handle.drain(..) { + // We expect to receive either a Page Fault or `remove` + // event (if the balloon device is enabled). + match event { + userfaultfd::Event::Pagefault { addr, .. } => { + if !uffd_handler.serve_pf(addr.cast(), uffd_handler.page_size) { + deferred_events.push(event); + } + } + userfaultfd::Event::Remove { start, end } => uffd_handler + .update_mem_state_mappings(start as u64, end as u64, MemPageState::Removed), + _ => panic!("Unexpected event on userfaultfd"), + } + } + + // We assume that really only the above removed/pagefault interaction can result in + // deferred events. In that scenario, the loop will always terminate (unless + // newly arriving `remove` events end up indefinitely blocking it, but there's nothing + // we can do about that, and it's a largely theoretical problem). + if deferred_events.is_empty() { + break; } - userfaultfd::Event::Remove { start, end } => uffd_handler.update_mem_state_mappings( - start as u64, - end as u64, - MemPageState::Removed, - ), - _ => panic!("Unexpected event on userfaultfd"), } }); } From f6bd4b630a829975e9020103f613b57bf89f93d1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 16:00:40 +0000 Subject: [PATCH 197/464] doc: Update Changelog Add entry about the UFFD fix. Signed-off-by: Patrick Roy --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6a8e1b2ded..30f5b70330c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,10 @@ and this project adheres to - [#5007](https://github.com/firecracker-microvm/firecracker/pull/5007): Fixed watchdog softlockup warning on x86_64 guests when a vCPU is paused during GDB debugging. +- [#5021](https://github.com/firecracker-microvm/firecracker/pull/5021) If a + balloon device is inflated post UFFD-backed snapshot restore, Firecracker now + causes `remove` UFFD messages to be sent to the UFFD handler. Previously, no + such message would be sent. ## [1.10.1] From 43247e4226c4c7a9414f35e7bdbdf976b1de15b4 Mon Sep 17 00:00:00 2001 From: Andrew Yao Date: Tue, 7 May 2024 11:25:44 -0500 Subject: [PATCH 198/464] Utilized option instead of vector to store irq lines Each MMIO device in Firecracker only utilizes at most one irq line, so capture this property at the type level. Signed-off-by: Andrew Yao Signed-off-by: Patrick Roy --- src/vmm/src/device_manager/mmio.rs | 88 ++++++++++++++---------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index 635bc1bc6e0..cab6e6d367b 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -7,6 +7,7 @@ use std::collections::HashMap; use std::fmt::Debug; +use std::num::NonZeroU32; use std::sync::{Arc, Mutex}; #[cfg(target_arch = "x86_64")] @@ -79,8 +80,8 @@ pub struct MMIODeviceInfo { pub addr: u64, /// Mmio addr range length. pub len: u64, - /// Used Irq line(s) for the device. - pub irqs: Vec, + /// Used Irq line for the device. + pub irq: Option, // NOTE: guaranteed to be a value not 0, 0 is not allowed } #[cfg(target_arch = "x86_64")] @@ -150,7 +151,12 @@ impl MMIODeviceManager { resource_allocator: &mut ResourceAllocator, irq_count: u32, ) -> Result { - let irqs = resource_allocator.allocate_gsi(irq_count)?; + let irq = match resource_allocator.allocate_gsi(irq_count)?[..] { + [] => None, + [irq] => NonZeroU32::new(irq), + _ => return Err(MmioError::InvalidIrqConfig), + }; + let device_info = MMIODeviceInfo { addr: resource_allocator.allocate_mmio_memory( MMIO_LEN, @@ -158,7 +164,7 @@ impl MMIODeviceManager { AllocPolicy::FirstMatch, )?, len: MMIO_LEN, - irqs, + irq, }; Ok(device_info) } @@ -187,9 +193,9 @@ impl MMIODeviceManager { ) -> Result<(), MmioError> { // Our virtio devices are currently hardcoded to use a single IRQ. // Validate that requirement. - if device_info.irqs.len() != 1 { + let Some(irq) = device_info.irq else { return Err(MmioError::InvalidIrqConfig); - } + }; let identifier; { let locked_device = mmio_device.locked_device(); @@ -201,11 +207,8 @@ impl MMIODeviceManager { vm.register_ioevent(queue_evt, &io_addr, u32::try_from(i).unwrap()) .map_err(MmioError::RegisterIoEvent)?; } - vm.register_irqfd( - &locked_device.interrupt_trigger().irq_evt, - device_info.irqs[0], - ) - .map_err(MmioError::RegisterIrqFd)?; + vm.register_irqfd(&locked_device.interrupt_trigger().irq_evt, irq.get()) + .map_err(MmioError::RegisterIrqFd)?; } self.register_mmio_device( @@ -230,7 +233,7 @@ impl MMIODeviceManager { .add_virtio_mmio_device( device_info.len, GuestAddress(device_info.addr), - device_info.irqs[0], + device_info.irq.unwrap().get(), None, ) .map_err(MmioError::Cmdline) @@ -257,7 +260,7 @@ impl MMIODeviceManager { device_info.len, // We are sure that `irqs` has at least one element; allocate_mmio_resources makes // sure of it. - device_info.irqs[0], + device_info.irq.unwrap().get(), )?; } Ok(device_info) @@ -289,7 +292,7 @@ impl MMIODeviceManager { .unwrap() .serial .interrupt_evt(), - device_info.irqs[0], + device_info.irq.unwrap().get(), ) .map_err(MmioError::RegisterIrqFd)?; @@ -525,7 +528,7 @@ impl DeviceInfoForFDT for MMIODeviceInfo { self.addr } fn irq(&self) -> u32 { - self.irqs[0] + self.irq.unwrap().into() } fn length(&self) -> u64 { self.len @@ -574,11 +577,10 @@ mod tests { #[cfg(target_arch = "x86_64")] /// Gets the number of interrupts used by the devices registered. pub fn used_irqs_count(&self) -> usize { - let mut irq_number = 0; self.get_device_info() .iter() - .for_each(|(_, device_info)| irq_number += device_info.irqs.len()); - irq_number + .filter(|(_, device_info)| device_info.irq.is_some()) + .count() } } @@ -784,7 +786,10 @@ mod tests { ); assert_eq!( crate::arch::IRQ_BASE, - device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)].irqs[0] + device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)] + .irq + .unwrap() + .get() ); let id = "bar"; @@ -821,38 +826,31 @@ mod tests { } #[test] - fn test_slot_irq_allocation() { + fn test_no_irq_allocation() { let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); + let device_info = device_manager .allocate_mmio_resources(&mut resource_allocator, 0) .unwrap(); - assert_eq!(device_info.irqs.len(), 0); + assert!(device_info.irq.is_none()); + } + + #[test] + fn test_irq_allocation() { + let mut device_manager = MMIODeviceManager::new(); + let mut resource_allocator = ResourceAllocator::new().unwrap(); + let device_info = device_manager .allocate_mmio_resources(&mut resource_allocator, 1) .unwrap(); - assert_eq!(device_info.irqs[0], crate::arch::IRQ_BASE); - assert_eq!( - format!( - "{}", - device_manager - .allocate_mmio_resources( - &mut resource_allocator, - crate::arch::IRQ_MAX - crate::arch::IRQ_BASE + 1 - ) - .unwrap_err() - ), - "Failed to allocate requested resource: The requested resource is not available." - .to_string() - ); + assert_eq!(device_info.irq.unwrap().get(), crate::arch::IRQ_BASE); + } - let device_info = device_manager - .allocate_mmio_resources( - &mut resource_allocator, - crate::arch::IRQ_MAX - crate::arch::IRQ_BASE - 1, - ) - .unwrap(); - assert_eq!(device_info.irqs[16], crate::arch::IRQ_BASE + 17); + #[test] + fn test_allocation_failure() { + let mut device_manager = MMIODeviceManager::new(); + let mut resource_allocator = ResourceAllocator::new().unwrap(); assert_eq!( format!( "{}", @@ -860,11 +858,7 @@ mod tests { .allocate_mmio_resources(&mut resource_allocator, 2) .unwrap_err() ), - "Failed to allocate requested resource: The requested resource is not available." - .to_string() + "Invalid MMIO IRQ configuration.".to_string() ); - device_manager - .allocate_mmio_resources(&mut resource_allocator, 0) - .unwrap(); } } From 1a9a236b7e42708a14f14370c8d13e8a575495c0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 27 Jan 2025 15:53:35 +0000 Subject: [PATCH 199/464] refactor: remove unused `set_dirty_page_tracking()` function In addition to being unused, it was also wrong, because it only updated the flag on KVM's side, but kept firecracker's tracking disabled. Signed-off-by: Patrick Roy --- src/vmm/src/lib.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 618f5d7b6c3..9be5ba53d02 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -629,18 +629,6 @@ impl Vmm { Ok(bitmap) } - /// Enables or disables KVM dirty page tracking. - pub fn set_dirty_page_tracking(&mut self, enable: bool) -> Result<(), VmmError> { - // This function _always_ results in an ioctl update. The VMM is stateless in the sense - // that it's unaware of the current dirty page tracking setting. - // The VMM's consumer will need to cache the dirty tracking setting internally. For - // example, if this function were to be exposed through the VMM controller, the VMM - // resources should cache the flag. - self.vm - .set_kvm_memory_regions(&self.guest_memory, enable) - .map_err(VmmError::Vm) - } - /// Updates the path of the host file backing the emulated block device with id `drive_id`. /// We update the disk image on the device and its virtio configuration. pub fn update_block_device_path( From 441f6a8bbc9b23fb73292ff30a607b7d374c3d6f Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 16:53:11 +0000 Subject: [PATCH 200/464] refactor: drop `track_dirty_pages` parameter from memory_init We already know about dirty page tracking inside that function, based on whether the memory regions have a bitmap associated with them or not. So drop passing this information in again via a parameter, which saves us quite a bit of plumbing. Suggested-by: Nikita Kalyazin Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 9 +++------ src/vmm/src/device_manager/mmio.rs | 6 +++--- src/vmm/src/vstate/vm.rs | 27 ++++++++++++--------------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index fc23d8add0b..27de9f6afa6 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -155,7 +155,6 @@ fn create_vmm_and_vcpus( event_manager: &mut EventManager, guest_memory: GuestMemoryMmap, uffd: Option, - track_dirty_pages: bool, vcpu_count: u8, kvm_capabilities: Vec, ) -> Result<(Vmm, Vec), StartMicrovmError> { @@ -172,7 +171,7 @@ fn create_vmm_and_vcpus( kvm.check_memory(&guest_memory) .map_err(VmmError::Kvm) .map_err(StartMicrovmError::Internal)?; - vm.memory_init(&guest_memory, track_dirty_pages) + vm.memory_init(&guest_memory) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; @@ -292,7 +291,6 @@ pub fn build_microvm_for_boot( event_manager, guest_memory, None, - vm_resources.machine_config.track_dirty_pages, vm_resources.machine_config.vcpu_count, cpu_template.kvm_capabilities.clone(), )?; @@ -482,7 +480,6 @@ pub fn build_microvm_from_snapshot( event_manager, guest_memory, uffd, - vm_resources.machine_config.track_dirty_pages, vm_resources.machine_config.vcpu_count, microvm_state.kvm_state.kvm_cap_modifiers.clone(), )?; @@ -1140,7 +1137,7 @@ pub(crate) mod tests { let kvm = Kvm::new(vec![]).unwrap(); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_memory, false).unwrap(); + vm.memory_init(&guest_memory).unwrap(); let mmio_device_manager = MMIODeviceManager::new(); let acpi_device_manager = ACPIDeviceManager::new(); #[cfg(target_arch = "x86_64")] @@ -1394,7 +1391,7 @@ pub(crate) mod tests { let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); #[allow(unused_mut)] let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_memory, false).unwrap(); + vm.memory_init(&guest_memory).unwrap(); let evfd = EventFd::new(libc::EFD_NONBLOCK).unwrap(); #[cfg(target_arch = "x86_64")] diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index cab6e6d367b..d35c8b36650 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -666,7 +666,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem, false).unwrap(); + vm.memory_init(&guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -696,7 +696,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem, false).unwrap(); + vm.memory_init(&guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -751,7 +751,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem, false).unwrap(); + vm.memory_init(&guest_mem).unwrap(); let mem_clone = guest_mem.clone(); diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 1bcf191b8b9..19ca0b2a76c 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -129,12 +129,8 @@ impl Vm { } /// Initializes the guest memory. - pub fn memory_init( - &self, - guest_mem: &GuestMemoryMmap, - track_dirty_pages: bool, - ) -> Result<(), VmError> { - self.set_kvm_memory_regions(guest_mem, track_dirty_pages)?; + pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { + self.set_kvm_memory_regions(guest_mem)?; #[cfg(target_arch = "x86_64")] self.fd .set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) @@ -146,16 +142,17 @@ impl Vm { pub(crate) fn set_kvm_memory_regions( &self, guest_mem: &GuestMemoryMmap, - track_dirty_pages: bool, ) -> Result<(), VmError> { - let mut flags = 0u32; - if track_dirty_pages { - flags |= KVM_MEM_LOG_DIRTY_PAGES; - } guest_mem .iter() .zip(0u32..) .try_for_each(|(region, slot)| { + let flags = if region.bitmap().is_some() { + KVM_MEM_LOG_DIRTY_PAGES + } else { + 0 + }; + let memory_region = kvm_userspace_memory_region { slot, guest_phys_addr: region.start_addr().raw_value(), @@ -359,7 +356,7 @@ pub(crate) mod tests { pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm, GuestMemoryMmap) { let (kvm, vm) = setup_vm(); let gm = single_region_mem(mem_size); - vm.memory_init(&gm, false).unwrap(); + vm.memory_init(&gm).unwrap(); (kvm, vm, gm) } @@ -375,7 +372,7 @@ pub(crate) mod tests { let (_, vm) = setup_vm(); // Create valid memory region and test that the initialization is successful. let gm = single_region_mem(0x1000); - vm.memory_init(&gm, true).unwrap(); + vm.memory_init(&gm).unwrap(); } #[cfg(target_arch = "x86_64")] @@ -452,13 +449,13 @@ pub(crate) mod tests { let (_, vm) = setup_vm(); let gm = single_region_mem(0x1000); - let res = vm.set_kvm_memory_regions(&gm, false); + let res = vm.set_kvm_memory_regions(&gm); res.unwrap(); // Trying to set a memory region with a size that is not a multiple of GUEST_PAGE_SIZE // will result in error. let gm = single_region_mem(0x10); - let res = vm.set_kvm_memory_regions(&gm, false); + let res = vm.set_kvm_memory_regions(&gm); assert_eq!( res.unwrap_err().to_string(), "Cannot set the memory regions: Invalid argument (os error 22)" From d8358055d4b2046fe86095cc11fb840f147417cf Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 27 Jan 2025 15:48:29 +0000 Subject: [PATCH 201/464] refactor: drop `offset` field from `GuestMemoryRegionState` In praxis, the way we wrote our snapshot files has always been just writing all regions in-order. This mean that the offset of a region is simply the sum of the sizes of the preceding regions. The new `GuestMemoryMmap::create` code already computes the offsets for mapping the memory file this way, so drop the explicit calculation at snapshot creation time (as the calculated value isnt used by the restoration anymore). Do not bump the snapshot version number, because we already did so since the last release. Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 9 +++++---- src/vmm/src/vstate/memory.rs | 20 ++++++-------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index c9aadad10a9..5c352f3b260 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -584,13 +584,15 @@ fn create_guest_memory( ) -> Result<(GuestMemoryMmap, Vec), GuestMemoryFromUffdError> { let guest_memory = GuestMemoryMmap::from_state(None, mem_state, track_dirty_pages, huge_pages)?; let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions()); - for (mem_region, state_region) in guest_memory.iter().zip(mem_state.regions.iter()) { + let mut offset = 0; + for mem_region in guest_memory.iter() { backend_mappings.push(GuestRegionUffdMapping { base_host_virt_addr: mem_region.as_ptr() as u64, size: mem_region.size(), - offset: state_region.offset, + offset, page_size_kib: huge_pages.page_size_kib(), }); + offset += mem_region.size() as u64; } Ok((guest_memory, backend_mappings)) @@ -770,7 +772,6 @@ mod tests { regions: vec![GuestMemoryRegionState { base_address: 0, size: 0x20000, - offset: 0x10000, }], }; @@ -779,7 +780,7 @@ mod tests { assert_eq!(uffd_regions.len(), 1); assert_eq!(uffd_regions[0].size, 0x20000); - assert_eq!(uffd_regions[0].offset, 0x10000); + assert_eq!(uffd_regions[0].offset, 0); assert_eq!( uffd_regions[0].page_size_kib, HugePageConfig::None.page_size_kib() diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index a84fd6c4be4..6e6674ebef7 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -122,8 +122,6 @@ pub struct GuestMemoryRegionState { pub base_address: u64, /// Region size. pub size: usize, - /// Offset in file/buffer where the region is saved. - pub offset: u64, } /// Describes guest memory regions and their snapshot file mappings. @@ -232,6 +230,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { track_dirty_pages: bool, huge_pages: HugePageConfig, ) -> Result { + let mut offset = 0; match file { Some(f) => { if huge_pages.is_hugetlbfs() { @@ -242,10 +241,12 @@ impl GuestMemoryExtension for GuestMemoryMmap { .regions .iter() .map(|r| { - f.try_clone().map(|file_clone| { - let offset = FileOffset::new(file_clone, r.offset); + let fo = f.try_clone().map(|file_clone| { + let offset = FileOffset::new(file_clone, offset); (offset, GuestAddress(r.base_address), r.size) - }) + }); + offset += r.size as u64; + fo }) .collect::, std::io::Error>>() .map_err(MemoryError::FileError)?; @@ -266,15 +267,11 @@ impl GuestMemoryExtension for GuestMemoryMmap { /// Describes GuestMemoryMmap through a GuestMemoryState struct. fn describe(&self) -> GuestMemoryState { let mut guest_memory_state = GuestMemoryState::default(); - let mut offset = 0; self.iter().for_each(|region| { guest_memory_state.regions.push(GuestMemoryRegionState { base_address: region.start_addr().0, size: u64_to_usize(region.len()), - offset, }); - - offset += region.len(); }); guest_memory_state } @@ -536,7 +533,6 @@ mod tests { regions: vec![GuestMemoryRegionState { base_address: 0, size: 4096, - offset: 0, }], }; let file = TempFile::new().unwrap().into_file(); @@ -652,12 +648,10 @@ mod tests { GuestMemoryRegionState { base_address: 0, size: page_size, - offset: 0, }, GuestMemoryRegionState { base_address: page_size as u64 * 2, size: page_size, - offset: page_size as u64, }, ], }; @@ -679,12 +673,10 @@ mod tests { GuestMemoryRegionState { base_address: 0, size: page_size * 3, - offset: 0, }, GuestMemoryRegionState { base_address: page_size as u64 * 4, size: page_size * 3, - offset: page_size as u64 * 3, }, ], }; From b6f66fa5fd58f57e1bb75ee3de5acb41f5287c12 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 28 Jan 2025 16:00:43 +0000 Subject: [PATCH 202/464] doc: Include historic 3.0.0 snapshot bump We forgot to include this in the 1.9.0 changelog. Let's retroactively do it. Signed-off-by: Patrick Roy --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f5b70330c..544b5a41924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,7 +122,8 @@ and this project adheres to VMGenID support for microVMs running on ARM hosts with 6.1 guest kernels. Support for VMGenID via DeviceTree bindings exists only on mainline 6.10 Linux onwards. Users of Firecracker will need to backport the relevant patches on - top of their 6.1 kernels to make use of the feature. + top of their 6.1 kernels to make use of the feature. As a result, Firecracker + snapshot version is now 3.0.0 - [#4732](https://github.com/firecracker-microvm/firecracker/pull/4732), [#4733](https://github.com/firecracker-microvm/firecracker/pull/4733), [#4741](https://github.com/firecracker-microvm/firecracker/pull/4741), From 45ad785cd0129b148782f6c58a40d4775aeddef4 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 17:33:10 +0000 Subject: [PATCH 203/464] refactor(test): Replace duplicated code with loops Some tests in memory.rs were runnign effectively the same test scenario twice, the only difference being the state of dirty page tracking. Just use a loop over the two boolean values here to avoid the copy-paste. Also remove a leftover test that was referring to "guard pages", but actually only repeated one of the dirty page tracking blocks. Guard pages were removed in 71cf036e56ce19dcf3144fd26bef6ae728f5464b. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/memory.rs | 53 +++++++----------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 6e6674ebef7..63e4fdeadc7 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -431,8 +431,7 @@ mod tests { #[test] fn test_from_raw_regions() { - // Check dirty page tracking is off. - { + for dirty_page_tracking in [true, false] { let region_size = 0x10000; let regions = vec![ (GuestAddress(0x0), region_size), @@ -441,27 +440,14 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = - GuestMemoryMmap::from_raw_regions(®ions, false, HugePageConfig::None).unwrap(); - guest_memory.iter().for_each(|region| { - assert!(region.bitmap().is_none()); - }); - } - - // Check dirty page tracking is on. - { - let region_size = 0x10000; - let regions = vec![ - (GuestAddress(0x0), region_size), - (GuestAddress(0x10000), region_size), - (GuestAddress(0x20000), region_size), - (GuestAddress(0x30000), region_size), - ]; - - let guest_memory = - GuestMemoryMmap::from_raw_regions(®ions, true, HugePageConfig::None).unwrap(); + let guest_memory = GuestMemoryMmap::from_raw_regions( + ®ions, + dirty_page_tracking, + HugePageConfig::None, + ) + .unwrap(); guest_memory.iter().for_each(|region| { - assert!(region.bitmap().is_some()); + assert_eq!(region.bitmap().is_some(), dirty_page_tracking); }); } } @@ -497,32 +483,13 @@ mod tests { ), ]; - // Test that all regions are guarded. - { + for dirty_page_tracking in [true, false] { let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions.clone(), false, false).unwrap(); guest_memory.iter().for_each(|region| { assert_eq!(region.size(), region_size); assert!(region.file_offset().is_some()); - assert!(region.bitmap().is_none()); - }); - } - - // Check dirty page tracking is off. - { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(regions.clone(), false, false).unwrap(); - guest_memory.iter().for_each(|region| { - assert!(region.bitmap().is_none()); - }); - } - - // Check dirty page tracking is on. - { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(regions, true, false).unwrap(); - guest_memory.iter().for_each(|region| { - assert!(region.bitmap().is_some()); + assert_eq!(region.bitmap().is_some(), dirty_page_tracking); }); } } From 1bb9d1846b9c808e0a51f0a9bb773d20ba95fe69 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 30 Jan 2025 17:47:40 +0000 Subject: [PATCH 204/464] refactor: centralize GuestMemoryMmap creation In this day and age, Firecracker supports theoretically 4 different ways of backing guest memory: 1. Normal MAP_ANONYMOUS | MAP_PRIVATE memory 2. memfd backed memory, mapped as shared 3. direct mapping of a snapshot file 4. MAP_ANONYMOUS again, but this time regions are described by snapshot file. We have 3 different functions for creating these different backing stores, which then call each other and vm_memory's APIs. Clean this up by consolidating these into just one function that can be called with generic memory backing options, plus 3 wrappers for the three actually used ways of backing memory. For this, hoist up the hugepages/file-based restore incompatibility check, as with a dedicated function for dealing with the "snapshot restored by mapping file" case, this function simply will not take a huge pages argument, so we have to check this somewhere else. Signed-off-by: Patrick Roy --- .../devices/virtio/block/vhost_user/device.rs | 12 +- .../src/devices/virtio/block/virtio/io/mod.rs | 8 +- src/vmm/src/devices/virtio/vhost_user.rs | 28 +- src/vmm/src/persist.rs | 30 +- src/vmm/src/resources.rs | 4 +- src/vmm/src/test_utils/mod.rs | 2 +- src/vmm/src/vstate/memory.rs | 311 ++++++------------ 7 files changed, 134 insertions(+), 261 deletions(-) diff --git a/src/vmm/src/devices/virtio/block/vhost_user/device.rs b/src/vmm/src/devices/virtio/block/vhost_user/device.rs index 62218157c8b..cdd17e2ea98 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/device.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/device.rs @@ -378,7 +378,7 @@ mod tests { use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::mmio::VIRTIO_MMIO_INT_CONFIG; use crate::test_utils::create_tmp_socket; - use crate::vstate::memory::{FileOffset, GuestAddress, GuestMemoryExtension}; + use crate::vstate::memory::{GuestAddress, GuestMemoryExtension}; #[test] fn test_from_config() { @@ -778,12 +778,10 @@ mod tests { let region_size = 0x10000; let file = TempFile::new().unwrap().into_file(); file.set_len(region_size as u64).unwrap(); - let regions = vec![( - FileOffset::new(file.try_clone().unwrap(), 0x0), - GuestAddress(0x0), - region_size, - )]; - let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap(); + let regions = vec![(GuestAddress(0x0), region_size)]; + let guest_memory = + GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) + .unwrap(); // During actiavion of the device features, memory and queues should be set and activated. vhost_block.activate(guest_memory).unwrap(); diff --git a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs index 09e86b6968d..cc49dae3eb7 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs @@ -230,8 +230,12 @@ pub mod tests { } fn create_mem() -> GuestMemoryMmap { - GuestMemoryMmap::from_raw_regions(&[(GuestAddress(0), MEM_LEN)], true, HugePageConfig::None) - .unwrap() + GuestMemoryMmap::anonymous( + [(GuestAddress(0), MEM_LEN)].into_iter(), + true, + HugePageConfig::None, + ) + .unwrap() } fn check_dirty_mem(mem: &GuestMemoryMmap, addr: GuestAddress, len: u32) { diff --git a/src/vmm/src/devices/virtio/vhost_user.rs b/src/vmm/src/devices/virtio/vhost_user.rs index ad86c9942af..cca506a57c2 100644 --- a/src/vmm/src/devices/virtio/vhost_user.rs +++ b/src/vmm/src/devices/virtio/vhost_user.rs @@ -466,7 +466,7 @@ mod tests { use super::*; use crate::test_utils::create_tmp_socket; - use crate::vstate::memory::{FileOffset, GuestAddress, GuestMemoryExtension}; + use crate::vstate::memory::{GuestAddress, GuestMemoryExtension}; #[test] fn test_new() { @@ -759,19 +759,13 @@ mod tests { let file_size = 2 * region_size; file.set_len(file_size as u64).unwrap(); let regions = vec![ - ( - FileOffset::new(file.try_clone().unwrap(), 0x0), - GuestAddress(0x0), - region_size, - ), - ( - FileOffset::new(file.try_clone().unwrap(), 0x10000), - GuestAddress(0x10000), - region_size, - ), + (GuestAddress(0x0), region_size), + (GuestAddress(0x10000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap(); + let guest_memory = + GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) + .unwrap(); vuh.update_mem_table(&guest_memory).unwrap(); @@ -883,13 +877,11 @@ mod tests { let region_size = 0x10000; let file = TempFile::new().unwrap().into_file(); file.set_len(region_size as u64).unwrap(); - let regions = vec![( - FileOffset::new(file.try_clone().unwrap(), 0x0), - GuestAddress(0x0), - region_size, - )]; + let regions = vec![(GuestAddress(0x0), region_size)]; - let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap(); + let guest_memory = + GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) + .unwrap(); let mut queue = Queue::new(69); queue.initialize(&guest_memory).unwrap(); diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 5c352f3b260..3c5f3e7e754 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -448,16 +448,19 @@ pub fn restore_from_snapshot( let mem_state = µvm_state.memory_state; let (guest_memory, uffd) = match params.mem_backend.backend_type { - MemBackendType::File => ( - guest_memory_from_file( - mem_backend_path, - mem_state, - track_dirty_pages, - vm_resources.machine_config.huge_pages, + MemBackendType::File => { + if vm_resources.machine_config.huge_pages.is_hugetlbfs() { + return Err(RestoreFromSnapshotGuestMemoryError::File( + GuestMemoryFromFileError::HugetlbfsSnapshot, + ) + .into()); + } + ( + guest_memory_from_file(mem_backend_path, mem_state, track_dirty_pages) + .map_err(RestoreFromSnapshotGuestMemoryError::File)?, + None, ) - .map_err(RestoreFromSnapshotGuestMemoryError::File)?, - None, - ), + } MemBackendType::Uffd => guest_memory_from_uffd( mem_backend_path, mem_state, @@ -513,17 +516,17 @@ pub enum GuestMemoryFromFileError { File(#[from] std::io::Error), /// Failed to restore guest memory: {0} Restore(#[from] MemoryError), + /// Cannot restore hugetlbfs backed snapshot by mapping the memory file. Please use uffd. + HugetlbfsSnapshot, } fn guest_memory_from_file( mem_file_path: &Path, mem_state: &GuestMemoryState, track_dirty_pages: bool, - huge_pages: HugePageConfig, ) -> Result { let mem_file = File::open(mem_file_path)?; - let guest_mem = - GuestMemoryMmap::from_state(Some(&mem_file), mem_state, track_dirty_pages, huge_pages)?; + let guest_mem = GuestMemoryMmap::snapshot_file(mem_file, mem_state, track_dirty_pages)?; Ok(guest_mem) } @@ -582,7 +585,8 @@ fn create_guest_memory( track_dirty_pages: bool, huge_pages: HugePageConfig, ) -> Result<(GuestMemoryMmap, Vec), GuestMemoryFromUffdError> { - let guest_memory = GuestMemoryMmap::from_state(None, mem_state, track_dirty_pages, huge_pages)?; + let guest_memory = + GuestMemoryMmap::anonymous(mem_state.regions(), track_dirty_pages, huge_pages)?; let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions()); let mut offset = 0; for mem_region in guest_memory.iter() { diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 2928a22c6ca..d6c5fb31a5a 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -472,8 +472,8 @@ impl VmResources { ) } else { let regions = crate::arch::arch_memory_regions(self.machine_config.mem_size_mib << 20); - GuestMemoryMmap::from_raw_regions( - ®ions, + GuestMemoryMmap::anonymous( + regions.into_iter(), self.machine_config.track_dirty_pages, self.machine_config.huge_pages, ) diff --git a/src/vmm/src/test_utils/mod.rs b/src/vmm/src/test_utils/mod.rs index 1ba79a55231..2ca7f5ce773 100644 --- a/src/vmm/src/test_utils/mod.rs +++ b/src/vmm/src/test_utils/mod.rs @@ -34,7 +34,7 @@ pub fn single_region_mem_at(at: u64, size: usize) -> GuestMemoryMmap { /// Creates a [`GuestMemoryMmap`] with multiple regions and without dirty page tracking. pub fn multi_region_mem(regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap { - GuestMemoryMmap::from_raw_regions(regions, false, HugePageConfig::None) + GuestMemoryMmap::anonymous(regions.iter().copied(), false, HugePageConfig::None) .expect("Cannot initialize memory") } diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 63e4fdeadc7..a9e16a8c2e6 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -8,6 +8,7 @@ use std::fs::File; use std::io::SeekFrom; +use libc::c_int; use serde::{Deserialize, Serialize}; pub use vm_memory::bitmap::{AtomicBitmap, Bitmap, BitmapSlice, BS}; pub use vm_memory::mmap::MmapRegionBuilder; @@ -19,6 +20,7 @@ pub use vm_memory::{ use vm_memory::{Error as VmMemoryError, GuestMemoryError, WriteVolatile}; use vmm_sys_util::errno; +use crate::arch::arch_memory_regions; use crate::utils::{get_page_size, u64_to_usize}; use crate::vmm_config::machine_config::HugePageConfig; use crate::DirtyBitmap; @@ -51,8 +53,6 @@ pub enum MemoryError { Memfd(memfd::Error), /// Cannot resize memfd file: {0} MemfdSetLen(std::io::Error), - /// Cannot restore hugetlbfs backed snapshot by mapping the memory file. Please use uffd. - HugetlbfsSnapshot, } /// Defines the interface for snapshotting memory. @@ -60,35 +60,59 @@ pub trait GuestMemoryExtension where Self: Sized, { + /// Creates a [`GuestMemoryMmap`] with the given configuration + fn create( + regions: impl Iterator, + mmap_flags: libc::c_int, + file: Option, + track_dirty_pages: bool, + ) -> Result; + /// Creates a GuestMemoryMmap with `size` in MiB backed by a memfd. fn memfd_backed( mem_size_mib: usize, track_dirty_pages: bool, huge_pages: HugePageConfig, - ) -> Result; + ) -> Result { + let memfd_file = create_memfd(mem_size_mib, huge_pages.into())?.into_file(); + let regions = arch_memory_regions(mem_size_mib << 20).into_iter(); - /// Creates a GuestMemoryMmap from raw regions. - fn from_raw_regions( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result; + Self::create( + regions, + libc::MAP_SHARED | huge_pages.mmap_flags(), + Some(memfd_file), + track_dirty_pages, + ) + } /// Creates a GuestMemoryMmap from raw regions. - fn from_raw_regions_file( - regions: Vec<(FileOffset, GuestAddress, usize)>, + fn anonymous( + regions: impl Iterator, track_dirty_pages: bool, - shared: bool, - ) -> Result; + huge_pages: HugePageConfig, + ) -> Result { + Self::create( + regions, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | huge_pages.mmap_flags(), + None, + track_dirty_pages, + ) + } /// Creates a GuestMemoryMmap given a `file` containing the data /// and a `state` containing mapping information. - fn from_state( - file: Option<&File>, + fn snapshot_file( + file: File, state: &GuestMemoryState, track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result; + ) -> Result { + Self::create( + state.regions(), + libc::MAP_PRIVATE, + Some(file), + track_dirty_pages, + ) + } /// Describes GuestMemoryMmap through a GuestMemoryState struct. fn describe(&self) -> GuestMemoryState; @@ -131,137 +155,51 @@ pub struct GuestMemoryState { pub regions: Vec, } -impl GuestMemoryExtension for GuestMemoryMmap { - /// Creates a GuestMemoryMmap with `size` in MiB backed by a memfd. - fn memfd_backed( - mem_size_mib: usize, - track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result { - let memfd_file = create_memfd(mem_size_mib, huge_pages.into())?.into_file(); - - let mut offset: u64 = 0; - let regions = crate::arch::arch_memory_regions(mem_size_mib << 20) +impl GuestMemoryState { + /// Turns this [`GuestMemoryState`] into a description of guest memory regions as understood + /// by the creation functions of [`GuestMemoryExtensions`] + pub fn regions(&self) -> impl Iterator + '_ { + self.regions .iter() - .map(|(guest_address, region_size)| { - let file_clone = memfd_file.try_clone().map_err(MemoryError::FileError)?; - let file_offset = FileOffset::new(file_clone, offset); - offset += *region_size as u64; - Ok((file_offset, *guest_address, *region_size)) - }) - .collect::, MemoryError>>()?; - - Self::from_raw_regions_file(regions, track_dirty_pages, true) + .map(|region| (GuestAddress(region.base_address), region.size)) } +} - /// Creates a GuestMemoryMmap from raw regions backed by anonymous memory. - fn from_raw_regions( - regions: &[(GuestAddress, usize)], +impl GuestMemoryExtension for GuestMemoryMmap { + fn create( + regions: impl Iterator, + mmap_flags: c_int, + file: Option, track_dirty_pages: bool, - huge_pages: HugePageConfig, ) -> Result { - let prot = libc::PROT_READ | libc::PROT_WRITE; - // MAP_NORESERVE for 4K-backed page regions means that no swap space will be reserved for - // the region. For hugetlbfs regions, it means that pages in the hugetlbfs pool will - // not be reserved at mmap-time. This means that instead of failing at mmap-time if - // the hugetlbfs page pool is too small to accommodate the entire VM, Firecracker might - // receive a SIGBUS if a pagefault ever cannot be served due to the pool being depleted. - let flags = - libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | huge_pages.mmap_flags(); - + let mut offset = 0; let regions = regions - .iter() - .map(|(guest_address, region_size)| { - let bitmap = match track_dirty_pages { - true => Some(AtomicBitmap::with_len(*region_size)), - false => None, - }; - let region = MmapRegionBuilder::new_with_bitmap(*region_size, bitmap) - .with_mmap_prot(prot) - .with_mmap_flags(flags) - .build() - .map_err(MemoryError::MmapRegionError)?; - - GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) - }) - .collect::, MemoryError>>()?; + .map(|(start, size)| { + let mut builder = MmapRegionBuilder::new_with_bitmap( + size, + track_dirty_pages.then(|| AtomicBitmap::with_len(size)), + ) + .with_mmap_prot(libc::PROT_READ | libc::PROT_WRITE) + .with_mmap_flags(libc::MAP_NORESERVE | mmap_flags); - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } + if let Some(ref file) = file { + let file_offset = + FileOffset::new(file.try_clone().map_err(MemoryError::FileError)?, offset); - /// Creates a GuestMemoryMmap from raw regions backed by file. - fn from_raw_regions_file( - regions: Vec<(FileOffset, GuestAddress, usize)>, - track_dirty_pages: bool, - shared: bool, - ) -> Result { - let prot = libc::PROT_READ | libc::PROT_WRITE; - let flags = if shared { - libc::MAP_NORESERVE | libc::MAP_SHARED - } else { - libc::MAP_NORESERVE | libc::MAP_PRIVATE - }; - let regions = regions - .into_iter() - .map(|(file_offset, guest_address, region_size)| { - let bitmap = match track_dirty_pages { - true => Some(AtomicBitmap::with_len(region_size)), - false => None, - }; - let region = MmapRegionBuilder::new_with_bitmap(region_size, bitmap) - .with_mmap_prot(prot) - .with_mmap_flags(flags) - .with_file_offset(file_offset) - .build() - .map_err(MemoryError::MmapRegionError)?; - - GuestRegionMmap::new(region, guest_address).map_err(MemoryError::VmMemoryError) - }) - .collect::, MemoryError>>()?; + builder = builder.with_file_offset(file_offset); + } - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } + offset += size as u64; - /// Creates a GuestMemoryMmap backed by a `file` if present, otherwise backed - /// by anonymous memory. Memory layout and ranges are described in `state` param. - fn from_state( - file: Option<&File>, - state: &GuestMemoryState, - track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result { - let mut offset = 0; - match file { - Some(f) => { - if huge_pages.is_hugetlbfs() { - return Err(MemoryError::HugetlbfsSnapshot); - } + GuestRegionMmap::new( + builder.build().map_err(MemoryError::MmapRegionError)?, + start, + ) + .map_err(MemoryError::VmMemoryError) + }) + .collect::, _>>()?; - let regions = state - .regions - .iter() - .map(|r| { - let fo = f.try_clone().map(|file_clone| { - let offset = FileOffset::new(file_clone, offset); - (offset, GuestAddress(r.base_address), r.size) - }); - offset += r.size as u64; - fo - }) - .collect::, std::io::Error>>() - .map_err(MemoryError::FileError)?; - - Self::from_raw_regions_file(regions, track_dirty_pages, false) - } - None => { - let regions = state - .regions - .iter() - .map(|r| (GuestAddress(r.base_address), r.size)) - .collect::>(); - Self::from_raw_regions(®ions, track_dirty_pages, huge_pages) - } - } + GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) } /// Describes GuestMemoryMmap through a GuestMemoryState struct. @@ -430,7 +368,7 @@ mod tests { use crate::utils::get_page_size; #[test] - fn test_from_raw_regions() { + fn test_anonymous() { for dirty_page_tracking in [true, false] { let region_size = 0x10000; let regions = vec![ @@ -440,8 +378,8 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions( - ®ions, + let guest_memory = GuestMemoryMmap::anonymous( + regions.into_iter(), dirty_page_tracking, HugePageConfig::None, ) @@ -452,66 +390,6 @@ mod tests { } } - #[test] - fn test_from_raw_regions_file() { - let region_size = 0x10000; - - let file = TempFile::new().unwrap().into_file(); - let file_size = 4 * region_size; - file.set_len(file_size as u64).unwrap(); - - let regions = vec![ - ( - FileOffset::new(file.try_clone().unwrap(), 0x0), - GuestAddress(0x0), - region_size, - ), - ( - FileOffset::new(file.try_clone().unwrap(), 0x10000), - GuestAddress(0x10000), - region_size, - ), - ( - FileOffset::new(file.try_clone().unwrap(), 0x20000), - GuestAddress(0x20000), - region_size, - ), - ( - FileOffset::new(file.try_clone().unwrap(), 0x30000), - GuestAddress(0x30000), - region_size, - ), - ]; - - for dirty_page_tracking in [true, false] { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(regions.clone(), false, false).unwrap(); - guest_memory.iter().for_each(|region| { - assert_eq!(region.size(), region_size); - assert!(region.file_offset().is_some()); - assert_eq!(region.bitmap().is_some(), dirty_page_tracking); - }); - } - } - - #[test] - fn test_from_state() { - let state = GuestMemoryState { - regions: vec![GuestMemoryRegionState { - base_address: 0, - size: 4096, - }], - }; - let file = TempFile::new().unwrap().into_file(); - - // No mapping of snapshots that were taken with hugetlbfs enabled - let err = - GuestMemoryMmap::from_state(Some(&file), &state, false, HugePageConfig::Hugetlbfs2M) - .unwrap_err(); - - assert!(matches!(err, MemoryError::HugetlbfsSnapshot), "{:?}", err); - } - #[test] fn test_mark_dirty() { let page_size = get_page_size().unwrap(); @@ -523,7 +401,7 @@ mod tests { (GuestAddress(region_size as u64 * 2), region_size), // pages 6-8 ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(®ions, true, HugePageConfig::None).unwrap(); + GuestMemoryMmap::anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(); let dirty_map = [ // page 0: not dirty @@ -578,8 +456,8 @@ mod tests { let region_size = page_size * 3; // Test with a single region - let guest_memory = GuestMemoryMmap::from_raw_regions( - &[(GuestAddress(0), region_size)], + let guest_memory = GuestMemoryMmap::anonymous( + [(GuestAddress(0), region_size)].into_iter(), false, HugePageConfig::None, ) @@ -593,7 +471,7 @@ mod tests { (GuestAddress(region_size as u64 * 2), region_size), // pages 6-8 ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(®ions, true, HugePageConfig::None).unwrap(); + GuestMemoryMmap::anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(); check_serde(&guest_memory); } @@ -607,7 +485,7 @@ mod tests { (GuestAddress(page_size as u64 * 2), page_size), ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(&mem_regions[..], true, HugePageConfig::None) + GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) .unwrap(); let expected_memory_state = GuestMemoryState { @@ -632,7 +510,7 @@ mod tests { (GuestAddress(page_size as u64 * 4), page_size * 3), ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(&mem_regions[..], true, HugePageConfig::None) + GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) .unwrap(); let expected_memory_state = GuestMemoryState { @@ -665,7 +543,8 @@ mod tests { (region_2_address, region_size), ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(&mem_regions, true, HugePageConfig::None).unwrap(); + GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -687,13 +566,8 @@ mod tests { let mut memory_file = TempFile::new().unwrap().into_file(); guest_memory.dump(&mut memory_file).unwrap(); - let restored_guest_memory = GuestMemoryMmap::from_state( - Some(&memory_file), - &memory_state, - false, - HugePageConfig::None, - ) - .unwrap(); + let restored_guest_memory = + GuestMemoryMmap::snapshot_file(memory_file, &memory_state, false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; page_size * 2]; @@ -721,7 +595,8 @@ mod tests { (region_2_address, region_size), ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(&mem_regions, true, HugePageConfig::None).unwrap(); + GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -751,8 +626,7 @@ mod tests { // We can restore from this because this is the first dirty dump. let restored_guest_memory = - GuestMemoryMmap::from_state(Some(&file), &memory_state, false, HugePageConfig::None) - .unwrap(); + GuestMemoryMmap::snapshot_file(file, &memory_state, false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; region_size]; @@ -809,7 +683,8 @@ mod tests { (region_2_address, region_size), ]; let guest_memory = - GuestMemoryMmap::from_raw_regions(&mem_regions, true, HugePageConfig::None).unwrap(); + GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { From 30c77f389437c3feb8b7afc9a9322541bb0cc019 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Mon, 3 Feb 2025 16:25:58 +0000 Subject: [PATCH 205/464] test(conftest): save ssh key on test failure Since ssh keys are now generated on the test machine, we need to preserve the key in test artifacts to be able to debug a test failure. Signed-off-by: Nikita Kalyazin --- tests/conftest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 41e0fbf2721..552ba25c4ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,6 +22,7 @@ import inspect import json import os +import platform import shutil import sys import tempfile @@ -340,6 +341,7 @@ def microvm_factory(request, record_property, results_dir, netns_factory): uvm_data = results_dir / uvm.id uvm_data.mkdir() uvm_data.joinpath("host-dmesg.log").write_text(dmesg.stdout) + shutil.copy(f"/firecracker/build/img/{platform.machine()}/id_rsa", uvm_data) uvm_root = Path(uvm.chroot()) for item in os.listdir(uvm_root): From c862760999f15d27034098a53a4d5bee3fba829d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:33:53 +0000 Subject: [PATCH 206/464] build(deps): Bump the firecracker group with 8 updates Bumps the firecracker group with 8 updates: | Package | From | To | | --- | --- | --- | | [syn](https://github.com/dtolnay/syn) | `2.0.96` | `2.0.98` | | [serde_json](https://github.com/serde-rs/json) | `1.0.137` | `1.0.138` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.10` | `1.2.11` | | [cmake](https://github.com/rust-lang/cmake-rs) | `0.1.52` | `0.1.53` | | [ryu](https://github.com/dtolnay/ryu) | `1.0.18` | `1.0.19` | | [toml_edit](https://github.com/toml-rs/toml) | `0.22.22` | `0.22.23` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.15` | `1.0.16` | | [winnow](https://github.com/winnow-rs/winnow) | `0.6.24` | `0.7.0` | Updates `syn` from 2.0.96 to 2.0.98 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.96...2.0.98) Updates `serde_json` from 1.0.137 to 1.0.138 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.137...v1.0.138) Updates `cc` from 1.2.10 to 1.2.11 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.10...cc-v1.2.11) Updates `cmake` from 0.1.52 to 0.1.53 - [Release notes](https://github.com/rust-lang/cmake-rs/releases) - [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.52...v0.1.53) Updates `ryu` from 1.0.18 to 1.0.19 - [Release notes](https://github.com/dtolnay/ryu/releases) - [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.19) Updates `toml_edit` from 0.22.22 to 0.22.23 - [Commits](https://github.com/toml-rs/toml/compare/v0.22.22...v0.22.23) Updates `unicode-ident` from 1.0.15 to 1.0.16 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.15...1.0.16) Updates `winnow` from 0.6.24 to 0.7.0 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.6.24...v0.7.0) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cmake dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: ryu dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: toml_edit dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 32 ++++++++++++++-------------- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 4 ++-- src/log-instrument-macros/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de011b07a1d..4b8441f50bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.10" +version = "1.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf" dependencies = [ "jobserver", "libc", @@ -396,9 +396,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.52" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +checksum = "e24a03c8b52922d68a1589ad61032f2c1aa5a8158d2aa0d93c6e9534944bbad6" dependencies = [ "cc", ] @@ -1166,9 +1166,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "same-file" @@ -1224,9 +1224,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.137" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -1288,9 +1288,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1379,9 +1379,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ "indexmap", "serde", @@ -1404,9 +1404,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-xid" @@ -1737,9 +1737,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.24" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419" dependencies = [ "memchr", ] diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 4539472c68f..69fa3a24fce 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -14,7 +14,7 @@ clap = { version = "4.5.27", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" -syn = { version = "2.0.96", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +syn = { version = "2.0.98", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index ad6d370aafc..fc88b3c122f 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -15,7 +15,7 @@ displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.137" +serde_json = "1.0.138" thiserror = "2.0.11" vmm = { path = "../vmm" } diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index cdb89d174d3..43ecc1e9dbe 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -24,7 +24,7 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } serde = { version = "1.0.217", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.137" +serde_json = "1.0.138" thiserror = "2.0.11" timerfd = "1.6.0" utils = { path = "../utils" } @@ -43,7 +43,7 @@ userfaultfd = "0.8.1" [build-dependencies] seccompiler = { path = "../seccompiler" } serde = { version = "1.0.217" } -serde_json = "1.0.137" +serde_json = "1.0.138" [features] tracing = ["log-instrument", "utils/tracing", "vmm/tracing"] diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 471b4b66159..3126679cfba 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] proc-macro2 = "1.0.93" quote = "1.0.38" -syn = { version = "2.0.96", features = ["full", "extra-traits"] } +syn = { version = "2.0.98", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 86c8f2e4177..8e465ce3563 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -21,7 +21,7 @@ clap = { version = "4.5.27", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.137" +serde_json = "1.0.138" thiserror = "2.0.11" zerocopy = { version = "0.8.14" } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 4bbb146ca18..0c15b57ef12 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -33,7 +33,7 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } semver = { version = "1.0.25", features = ["serde"] } serde = { version = "1.0.217", features = ["derive", "rc"] } -serde_json = "1.0.137" +serde_json = "1.0.138" slab = "0.4.7" thiserror = "2.0.11" timerfd = "1.5.0" From df2c3ac96d3d671538e7092045ec2204b3727244 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 5 Feb 2025 16:59:39 +0000 Subject: [PATCH 207/464] fix: stop `dup(2)`-ing fds when setting up guest memory Currently, when backing guest memory by memfd or when mmaping a snapshot file, we duplicate the file descriptor once per memslot. This is not necessary: KVM will happily accept the same fd into multiple memslots, and even rust-vmm supports APIs for this (by storing `Arc` instead of just `File` in `FileOffset`, we can actually share the same `File` reference between multiple memory regions). So let's make use of this capability. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/memory.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index a9e16a8c2e6..b89de3453c2 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -7,6 +7,7 @@ use std::fs::File; use std::io::SeekFrom; +use std::sync::Arc; use libc::c_int; use serde::{Deserialize, Serialize}; @@ -35,8 +36,6 @@ pub type GuestMmapRegion = vm_memory::MmapRegion>; /// Errors associated with dumping guest memory to file. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum MemoryError { - /// Cannot access file: {0} - FileError(std::io::Error), /// Cannot create memory: {0} CreateMemory(VmMemoryError), /// Cannot create memory region: {0} @@ -173,6 +172,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { track_dirty_pages: bool, ) -> Result { let mut offset = 0; + let file = file.map(Arc::new); let regions = regions .map(|(start, size)| { let mut builder = MmapRegionBuilder::new_with_bitmap( @@ -183,8 +183,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { .with_mmap_flags(libc::MAP_NORESERVE | mmap_flags); if let Some(ref file) = file { - let file_offset = - FileOffset::new(file.try_clone().map_err(MemoryError::FileError)?, offset); + let file_offset = FileOffset::from_arc(Arc::clone(file), offset); builder = builder.with_file_offset(file_offset); } From 567b1ea0af6c142c810763481c544e214213db79 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 31 Jan 2025 17:13:22 +0000 Subject: [PATCH 208/464] doc: clarify cross-kernel snapshot compatibility Simplify by just making the statement that we do not recommend it, and it generally doesnt work except for one limited case. Simplify the table by only listing what's working, an by having the first column directly refer to instance types (instead of cpu architectures, which we later map to instance types in the text). While we're at it, also update the table of contents at the top to include two sections it was missing. Closes #4912 Signed-off-by: Patrick Roy --- docs/snapshotting/snapshot-support.md | 37 +++++++++++---------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 910dde94ce7..e1294e1ac7d 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -25,6 +25,8 @@ - [Secure and insecure usage examples](#usage-examples) - [Reusing snapshotted states securely](#reusing-snapshotted-states-securely) - [Vsock device limitation](#vsock-device-limitation) +- [VMGenID device limitation](#vmgenid-device-limitation) +- [Where can I resume my snapshots?](#where-can-i-resume-my-snapshots) ## About microVM snapshotting @@ -638,28 +640,19 @@ might not be able to handle the injected notification and crash. We suggest to users that they take snapshots only after the guest kernel has completed booting, to avoid this issue. -## Snapshot compatibility across kernel versions +## Where can I resume my snapshots? -We have a mechanism in place to experiment with snapshot compatibility across -supported host kernel versions by generating snapshot artifacts through -[this test](../../tests/integration_tests/functional/test_snapshot_phase1.py) -and checking devices' functionality using -[this test](../../tests/integration_tests/functional/test_snapshot_restore_cross_kernel.py). -The test restores the snapshot and ensures that all the devices set-up (network -devices, disk, vsock, balloon and MMDS) are operational post-load. +Snapshots must be resumed on an software and hardware configuration which is +identical to what they were generated on. However, in limited cases, snapshots +can be resumed on identical hardware instances where they were taken on, but +using newer host kernel versions. While we do not provide any guarantees on this +setup (and do not recommend doing this in production), we are currently aware of +the compatibility table reported below: -In those tests the instance is fixed, except some combinations where we also -test across the same CPU family (Intel x86, Gravitons). In general cross-CPU -snapshots [are not supported](./versioning.md#cpu-model) +| .metal instance type | taken on host kernel | restored on host kernel | +| -------------------- | -------------------- | ----------------------- | +| {c5n,m5n,m6i,m6a} | 5.10 | 6.1 | -The tables below reflect the snapshot compatibility observed on the AWS -instances we support. - -**all** means all currently supported Intel/AMD/ARM metal instances (m6g, m7g, -m5n, c5n, m6i, m6a). It does not mean cross-instance, i.e. a snapshot taken on -m6i won't work on an m6g instance. - -| *CPU family* | *taken on host kernel* | *restored on host kernel* | *working?* | -| ------------ | ---------------------- | ------------------------- | ---------- | -| **x86_64** | 5.10 | 6.1 | Y | -| **x86_64** | 6.1 | 5.10 | N | +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. From 89f2cb2815f95c558ca7e40bb770c73f61286ce6 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Fri, 24 Jan 2025 12:09:19 +0000 Subject: [PATCH 209/464] fix: Fix rare failure in pause resume test Test with 1 vCPU when running the KVMCLOCK_CTRL tests so we don't error on intermittent issue with the soft lockup watchdog. Signed-off-by: Jack Thomson --- tests/integration_tests/functional/test_pause_resume.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_pause_resume.py b/tests/integration_tests/functional/test_pause_resume.py index 34b9a9a7229..ca2bb6936b3 100644 --- a/tests/integration_tests/functional/test_pause_resume.py +++ b/tests/integration_tests/functional/test_pause_resume.py @@ -141,7 +141,12 @@ def test_kvmclock_ctrl(uvm_plain_any): microvm = uvm_plain_any microvm.help.enable_console() microvm.spawn() - microvm.basic_config() + + # With 2 vCPUs under certain conditions soft lockup warnings can rarely be in dmesg causing this test to fail. + # Example of the warning: `watchdog: BUG: soft lockup - CPU#0 stuck for (x)s! [(udev-worker):758]` + # With 1 vCPU this intermittent issue doesn't occur. If the KVM_CLOCK_CTRL IOCTL is not made + # the test will fail with 1 vCPU, so we can assert the call to the IOCTL is made. + microvm.basic_config(vcpu_count=1) microvm.add_net_iface() microvm.start() From 44a50b451002a7e4a65959707b565dba9c39457d Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 7 Feb 2025 14:40:35 +0000 Subject: [PATCH 210/464] refactor(vmm): Remove unnecessary renames VmmConfig is parsed from Firecracker config JSON file. I don't know why we used different field names than names in the JSON format, which just makes it difficult to read code and readers have to keep the field mapping in their mind. Signed-off-by: Takahiro Itazuri --- src/vmm/src/resources.rs | 43 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index d6c5fb31a5a..024f8833b78 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -63,29 +63,20 @@ pub enum ResourcesError { /// Used for configuring a vmm from one single json passed to the Firecracker process. #[derive(Debug, Default, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] pub struct VmmConfig { - #[serde(rename = "balloon")] - balloon_device: Option, - #[serde(rename = "drives")] - block_devices: Vec, - #[serde(rename = "boot-source")] + balloon: Option, + drives: Vec, boot_source: BootSourceConfig, - #[serde(rename = "cpu-config")] cpu_config: Option, - #[serde(rename = "logger")] logger: Option, - #[serde(rename = "machine-config")] machine_config: Option, - #[serde(rename = "metrics")] metrics: Option, - #[serde(rename = "mmds-config")] mmds_config: Option, - #[serde(rename = "network-interfaces", default)] - net_devices: Vec, - #[serde(rename = "vsock")] - vsock_device: Option, - #[serde(rename = "entropy")] - entropy_device: Option, + #[serde(default)] + network_interfaces: Vec, + vsock: Option, + entropy: Option, } /// A data structure that encapsulates the device configurations @@ -152,19 +143,19 @@ impl VmResources { resources.build_boot_source(vmm_config.boot_source)?; - for drive_config in vmm_config.block_devices.into_iter() { + for drive_config in vmm_config.drives.into_iter() { resources.set_block_device(drive_config)?; } - for net_config in vmm_config.net_devices.into_iter() { + for net_config in vmm_config.network_interfaces.into_iter() { resources.build_net_device(net_config)?; } - if let Some(vsock_config) = vmm_config.vsock_device { + if let Some(vsock_config) = vmm_config.vsock { resources.set_vsock_device(vsock_config)?; } - if let Some(balloon_config) = vmm_config.balloon_device { + if let Some(balloon_config) = vmm_config.balloon { resources.set_balloon_device(balloon_config)?; } @@ -180,7 +171,7 @@ impl VmResources { resources.set_mmds_config(mmds_config, &instance_info.id)?; } - if let Some(entropy_device_config) = vmm_config.entropy_device { + if let Some(entropy_device_config) = vmm_config.entropy { resources.build_entropy_device(entropy_device_config)?; } @@ -484,17 +475,17 @@ impl VmResources { impl From<&VmResources> for VmmConfig { fn from(resources: &VmResources) -> Self { VmmConfig { - balloon_device: resources.balloon.get_config().ok(), - block_devices: resources.block.configs(), + balloon: resources.balloon.get_config().ok(), + drives: resources.block.configs(), boot_source: resources.boot_source.config.clone(), cpu_config: None, logger: None, machine_config: Some(resources.machine_config.clone()), metrics: None, mmds_config: resources.mmds_config(), - net_devices: resources.net_builder.configs(), - vsock_device: resources.vsock.config(), - entropy_device: resources.entropy.config(), + network_interfaces: resources.net_builder.configs(), + vsock: resources.vsock.config(), + entropy: resources.entropy.config(), } } } From b0e110b06225c44968812a5c901e00366bb4639c Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 7 Feb 2025 14:13:42 +0000 Subject: [PATCH 211/464] refactor(virtio-block): use a type for config space Instead of using a vector of bytes as a config space it is better to use a proper type. This was already done in the virtio-net device, so just repeat same in block device. Signed-off-by: Egor Lazarchuk --- .../src/devices/virtio/block/virtio/device.rs | 110 +++++++++--------- .../src/devices/virtio/block/virtio/mod.rs | 2 - .../devices/virtio/block/virtio/persist.rs | 7 +- 3 files changed, 58 insertions(+), 61 deletions(-) diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index fd352fe2539..5854fd8598f 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -8,21 +8,19 @@ use std::cmp; use std::convert::From; use std::fs::{File, OpenOptions}; -use std::io::{Seek, SeekFrom, Write}; +use std::io::{Seek, SeekFrom}; use std::os::linux::fs::MetadataExt; use std::path::PathBuf; use std::sync::Arc; use block_io::FileEngine; use serde::{Deserialize, Serialize}; +use vm_memory::ByteValued; use vmm_sys_util::eventfd::EventFd; use super::io::async_io; use super::request::*; -use super::{ - io as block_io, VirtioBlockError, BLOCK_CONFIG_SPACE_SIZE, BLOCK_QUEUE_SIZES, SECTOR_SHIFT, - SECTOR_SIZE, -}; +use super::{io as block_io, VirtioBlockError, BLOCK_QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE}; use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice}; use crate::devices::virtio::block::CacheType; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; @@ -155,20 +153,17 @@ impl DiskProperties { } default_id } +} - /// Provides vec containing the virtio block configuration space - /// buffer. The config space is populated with the disk size based - /// on the backing file size. - pub fn virtio_block_config_space(&self) -> Vec { - // The config space is little endian. - let mut config = Vec::with_capacity(BLOCK_CONFIG_SPACE_SIZE); - for i in 0..BLOCK_CONFIG_SPACE_SIZE { - config.push(((self.nsectors >> (8 * i)) & 0xff) as u8); - } - config - } +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +#[repr(C)] +pub struct ConfigSpace { + pub capacity: u64, } +// SAFETY: `ConfigSpace` contains only PODs in `repr(C)` or `repr(transparent)`, without padding. +unsafe impl ByteValued for ConfigSpace {} + /// Use this structure to set up the Block Device before booting the kernel. #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] @@ -246,7 +241,7 @@ pub struct VirtioBlock { // Virtio fields. pub avail_features: u64, pub acked_features: u64, - pub config_space: Vec, + pub config_space: ConfigSpace, pub activate_evt: EventFd, // Transport related fields. @@ -313,10 +308,14 @@ impl VirtioBlock { let queues = BLOCK_QUEUE_SIZES.iter().map(|&s| Queue::new(s)).collect(); + let config_space = ConfigSpace { + capacity: disk_properties.nsectors.to_le(), + }; + Ok(VirtioBlock { avail_features, acked_features: 0u64, - config_space: disk_properties.virtio_block_config_space(), + config_space, activate_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(VirtioBlockError::EventFd)?, queues, @@ -524,7 +523,7 @@ impl VirtioBlock { /// Update the backing file and the config space of the block device. pub fn update_disk_image(&mut self, disk_image_path: String) -> Result<(), VirtioBlockError> { self.disk.update(disk_image_path, self.read_only)?; - self.config_space = self.disk.virtio_block_config_space(); + self.config_space.capacity = self.disk.nsectors.to_le(); // virtio_block_config_space(); // Kick the driver to pick up the changes. self.irq_trigger.trigger_irq(IrqType::Config).unwrap(); @@ -598,28 +597,23 @@ impl VirtioDevice for VirtioBlock { &self.irq_trigger } - fn read_config(&self, offset: u64, mut data: &mut [u8]) { - let config_len = self.config_space.len() as u64; - if offset >= config_len { + fn read_config(&self, offset: u64, data: &mut [u8]) { + if let Some(config_space_bytes) = self.config_space.as_slice().get(u64_to_usize(offset)..) { + let len = config_space_bytes.len().min(data.len()); + data[..len].copy_from_slice(&config_space_bytes[..len]); + } else { error!("Failed to read config space"); self.metrics.cfg_fails.inc(); - return; - } - if let Some(end) = offset.checked_add(data.len() as u64) { - // This write can't fail, offset and end are checked against config_len. - data.write_all( - &self.config_space[u64_to_usize(offset)..u64_to_usize(cmp::min(end, config_len))], - ) - .unwrap(); } } fn write_config(&mut self, offset: u64, data: &[u8]) { + let config_space_bytes = self.config_space.as_mut_slice(); let start = usize::try_from(offset).ok(); let end = start.and_then(|s| s.checked_add(data.len())); let Some(dst) = start .zip(end) - .and_then(|(start, end)| self.config_space.get_mut(start..end)) + .and_then(|(start, end)| config_space_bytes.get_mut(start..end)) else { error!("Failed to write config space"); self.metrics.cfg_fails.inc(); @@ -673,7 +667,7 @@ impl Drop for VirtioBlock { #[cfg(test)] mod tests { use std::fs::metadata; - use std::io::Read; + use std::io::{Read, Write}; use std::os::unix::ffi::OsStrExt; use std::thread; use std::time::Duration; @@ -755,11 +749,6 @@ mod tests { assert_eq!(size, u64::from(SECTOR_SIZE) * num_sectors); assert_eq!(disk_properties.nsectors, num_sectors); - let cfg = disk_properties.virtio_block_config_space(); - assert_eq!(cfg.len(), BLOCK_CONFIG_SPACE_SIZE); - for (i, byte) in cfg.iter().enumerate() { - assert_eq!(*byte, ((num_sectors >> (8 * i)) & 0xff) as u8); - } // Testing `backing_file.virtio_block_disk_image_id()` implies // duplicating that logic in tests, so skipping it. @@ -803,20 +792,21 @@ mod tests { for engine in [FileEngineType::Sync, FileEngineType::Async] { let block = default_block(engine); - let mut actual_config_space = [0u8; BLOCK_CONFIG_SPACE_SIZE]; - block.read_config(0, &mut actual_config_space); + let mut actual_config_space = ConfigSpace::default(); + block.read_config(0, actual_config_space.as_mut_slice()); // This will read the number of sectors. // The block's backing file size is 0x1000, so there are 8 (4096/512) sectors. // The config space is little endian. - let expected_config_space: [u8; BLOCK_CONFIG_SPACE_SIZE] = - [0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let expected_config_space = ConfigSpace { capacity: 8 }; assert_eq!(actual_config_space, expected_config_space); // Invalid read. - let expected_config_space: [u8; BLOCK_CONFIG_SPACE_SIZE] = - [0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf]; + let expected_config_space = ConfigSpace { capacity: 696969 }; actual_config_space = expected_config_space; - block.read_config(BLOCK_CONFIG_SPACE_SIZE as u64 + 1, &mut actual_config_space); + block.read_config( + std::mem::size_of::() as u64 + 1, + actual_config_space.as_mut_slice(), + ); // Validate read failed (the config space was not updated). assert_eq!(actual_config_space, expected_config_space); @@ -828,33 +818,37 @@ mod tests { for engine in [FileEngineType::Sync, FileEngineType::Async] { let mut block = default_block(engine); - let expected_config_space: [u8; BLOCK_CONFIG_SPACE_SIZE] = - [0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - block.write_config(0, &expected_config_space); + let expected_config_space = ConfigSpace { capacity: 696969 }; + block.write_config(0, expected_config_space.as_slice()); - let mut actual_config_space = [0u8; BLOCK_CONFIG_SPACE_SIZE]; - block.read_config(0, &mut actual_config_space); + let mut actual_config_space = ConfigSpace::default(); + block.read_config(0, actual_config_space.as_mut_slice()); assert_eq!(actual_config_space, expected_config_space); // If priviledged user writes to `/dev/mem`, in block config space - byte by byte. - let expected_config_space = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x00, 0x11]; - for i in 0..expected_config_space.len() { - block.write_config(i as u64, &expected_config_space[i..=i]); + let expected_config_space = ConfigSpace { + capacity: 0x1122334455667788, + }; + let expected_config_space_slice = expected_config_space.as_slice(); + for (i, b) in expected_config_space_slice.iter().enumerate() { + block.write_config(i as u64, &[*b]); } - block.read_config(0, &mut actual_config_space); + block.read_config(0, actual_config_space.as_mut_slice()); assert_eq!(actual_config_space, expected_config_space); // Invalid write. - let new_config_space = [0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf]; - block.write_config(5, &new_config_space); + let new_config_space = ConfigSpace { + capacity: 0xDEADBEEF, + }; + block.write_config(5, new_config_space.as_slice()); // Make sure nothing got written. - block.read_config(0, &mut actual_config_space); + block.read_config(0, actual_config_space.as_mut_slice()); assert_eq!(actual_config_space, expected_config_space); // Large offset that may cause an overflow. - block.write_config(u64::MAX, &new_config_space); + block.write_config(u64::MAX, new_config_space.as_slice()); // Make sure nothing got written. - block.read_config(0, &mut actual_config_space); + block.read_config(0, actual_config_space.as_mut_slice()); assert_eq!(actual_config_space, expected_config_space); } } diff --git a/src/vmm/src/devices/virtio/block/virtio/mod.rs b/src/vmm/src/devices/virtio/block/virtio/mod.rs index 8a2045f19e5..8ea59a5aba4 100644 --- a/src/vmm/src/devices/virtio/block/virtio/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/mod.rs @@ -18,8 +18,6 @@ pub use self::request::*; pub use crate::devices::virtio::block::CacheType; use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; -/// Size of config space for block device. -pub const BLOCK_CONFIG_SPACE_SIZE: usize = 8; /// Sector shift for block device. pub const SECTOR_SHIFT: u8 = 9; /// Size of block sector. diff --git a/src/vmm/src/devices/virtio/block/virtio/persist.rs b/src/vmm/src/devices/virtio/block/virtio/persist.rs index 61bffbeaa40..caab2c13a5f 100644 --- a/src/vmm/src/devices/virtio/block/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/block/virtio/persist.rs @@ -6,6 +6,7 @@ use std::sync::atomic::AtomicU32; use std::sync::Arc; +use device::ConfigSpace; use serde::{Deserialize, Serialize}; use vmm_sys_util::eventfd::EventFd; @@ -122,10 +123,14 @@ impl Persist<'_> for VirtioBlock { DeviceState::Inactive }; + let config_space = ConfigSpace { + capacity: disk_properties.nsectors.to_le(), + }; + Ok(VirtioBlock { avail_features, acked_features, - config_space: disk_properties.virtio_block_config_space(), + config_space, activate_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(VirtioBlockError::EventFd)?, queues, From ab019ea2bb2905543243bd22465eb7379ba43740 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Fri, 7 Feb 2025 15:16:58 +0000 Subject: [PATCH 212/464] test(ab): unignore m6g/5.10 block m6g/5.10 block throughput results are no longer volatile, so we can reinsert it to the A/B testing. Signed-off-by: Nikita Kalyazin --- tools/ab_test.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tools/ab_test.py b/tools/ab_test.py index 2d03d9591a1..7349adcb862 100755 --- a/tools/ab_test.py +++ b/tools/ab_test.py @@ -44,13 +44,6 @@ IGNORED = [ # Network throughput on m6a.metal {"instance": "m6a.metal", "performance_test": "test_network_tcp_throughput"}, - # Block throughput for 1 vcpu on m6g.metal/5.10 - { - "performance_test": "test_block_performance", - "instance": "m6g.metal", - "host_kernel": "linux-5.10", - "vcpus": "1", - }, ] From 3ca2fab4f6ef43a7b9f90530c2f8a2cc8d92e17e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 16:46:30 +0000 Subject: [PATCH 213/464] build(deps): Bump the firecracker group with 14 updates Bumps the firecracker group with 14 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.14` | `0.8.17` | | [clap](https://github.com/clap-rs/clap) | `4.5.27` | `4.5.28` | | [uuid](https://github.com/uuid-rs/uuid) | `1.12.1` | `1.13.1` | | [derive_more](https://github.com/JelteF/derive_more) | `1.0.0` | `2.0.1` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.13.2` | `0.13.3` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.25.0` | `0.25.1` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.11` | `1.2.13` | | [clap_derive](https://github.com/clap-rs/clap) | `4.5.24` | `4.5.28` | | [cmake](https://github.com/rust-lang/cmake-rs) | `0.1.53` | `0.1.54` | | [derive_more-impl](https://github.com/JelteF/derive_more) | `1.0.0` | `2.0.1` | | [once_cell](https://github.com/matklad/once_cell) | `1.20.2` | `1.20.3` | | [toml](https://github.com/toml-rs/toml) | `0.8.19` | `0.8.20` | | [uuid-macro-internal](https://github.com/uuid-rs/uuid) | `1.12.1` | `1.13.1` | | [winnow](https://github.com/winnow-rs/winnow) | `0.7.0` | `0.7.2` | Updates `zerocopy` from 0.8.14 to 0.8.17 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.14...v0.8.17) Updates `clap` from 4.5.27 to 4.5.28 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.27...clap_complete-v4.5.28) Updates `uuid` from 1.12.1 to 1.13.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.12.1...1.13.1) Updates `derive_more` from 1.0.0 to 2.0.1 - [Release notes](https://github.com/JelteF/derive_more/releases) - [Changelog](https://github.com/JelteF/derive_more/blob/master/CHANGELOG.md) - [Commits](https://github.com/JelteF/derive_more/compare/v1.0.0...v2.0.1) Updates `aws-lc-fips-sys` from 0.13.2 to 0.13.3 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.2...aws-lc-fips-sys/v0.13.3) Updates `aws-lc-sys` from 0.25.0 to 0.25.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.25.0...aws-lc-sys/v0.25.1) Updates `cc` from 1.2.11 to 1.2.13 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.11...cc-v1.2.13) Updates `clap_derive` from 4.5.24 to 4.5.28 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.24...v4.5.28) Updates `cmake` from 0.1.53 to 0.1.54 - [Release notes](https://github.com/rust-lang/cmake-rs/releases) - [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.53...v0.1.54) Updates `derive_more-impl` from 1.0.0 to 2.0.1 - [Release notes](https://github.com/JelteF/derive_more/releases) - [Changelog](https://github.com/JelteF/derive_more/blob/master/CHANGELOG.md) - [Commits](https://github.com/JelteF/derive_more/compare/v1.0.0...v2.0.1) Updates `once_cell` from 1.20.2 to 1.20.3 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.20.3) Updates `toml` from 0.8.19 to 0.8.20 - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20) Updates `uuid-macro-internal` from 1.12.1 to 1.13.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.12.1...1.13.1) Updates `winnow` from 0.7.0 to 0.7.2 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.7.0...v0.7.2) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: derive_more dependency-type: direct:production update-type: version-update:semver-major dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_derive dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cmake dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: derive_more-impl dependency-type: indirect update-type: version-update:semver-major dependency-group: firecracker - dependency-name: once_cell dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: toml dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 149 ++++++++++++++++++++--------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 4 +- src/cpu-template-helper/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 4 +- src/snapshot-editor/Cargo.toml | 2 +- src/vmm/Cargo.toml | 4 +- 7 files changed, 114 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b8441f50bc..23367c3a153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.11", "vm-memory", - "zerocopy 0.8.14", + "zerocopy 0.8.17", ] [[package]] @@ -126,9 +126,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e4aa2478e3ff7e6c2624558abfdad004a57ba975974b4769a4c0d12831f143" +checksum = "29003a681b2b9465c1139bfb726da452a841a8b025f35953f3bce71139f10b21" dependencies = [ "bindgen 0.69.5", "cc", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2ddd3ada61a305e1d8bb6c005d1eaa7d14d903681edfc400406d523a9b491" +checksum = "54ac4f13dad353b209b34cbec082338202cbc01c8f00336b55c750c13ac91f8f" dependencies = [ "bindgen 0.69.5", "cc", @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.11" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" dependencies = [ "jobserver", "libc", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.27" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" +checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" dependencies = [ "clap_builder", "clap_derive", @@ -365,9 +365,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", @@ -396,9 +396,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.53" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24a03c8b52922d68a1589ad61032f2c1aa5a8158d2aa0d93c6e9534944bbad6" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] @@ -500,18 +500,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "1.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "1.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", @@ -668,7 +668,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", ] [[package]] @@ -972,9 +984,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "oorandom" @@ -1049,8 +1061,8 @@ dependencies = [ "bitflags 2.8.0", "lazy_static", "num-traits", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_xorshift", "regex-syntax", "unarray", @@ -1072,8 +1084,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.17", ] [[package]] @@ -1083,7 +1106,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", ] [[package]] @@ -1092,7 +1125,17 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", ] [[package]] @@ -1101,7 +1144,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1190,7 +1233,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.11", - "zerocopy 0.8.14", + "zerocopy 0.8.17", ] [[package]] @@ -1358,9 +1401,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -1473,20 +1516,20 @@ dependencies = [ [[package]] name = "uuid" -version = "1.12.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" +checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" dependencies = [ - "getrandom", - "rand", + "getrandom 0.3.1", + "rand 0.9.0", "uuid-macro-internal", ] [[package]] name = "uuid-macro-internal" -version = "1.12.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a86d88347b61a0e17b9908a67efcc594130830bf1045653784358dd023e294" +checksum = "d28dd23acb5f2fa7bd2155ab70b960e770596b3bb6395119b40476c3655dfba4" dependencies = [ "proc-macro2", "quote", @@ -1588,7 +1631,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.14", + "zerocopy 0.8.17", ] [[package]] @@ -1619,6 +1662,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "which" version = "4.4.2" @@ -1737,13 +1789,22 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1756,11 +1817,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.14" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" dependencies = [ - "zerocopy-derive 0.8.14", + "zerocopy-derive 0.8.17", ] [[package]] @@ -1776,9 +1837,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.14" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 17b5b5baa6f..ac4bbaaa47d 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.11" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.14", features = ["derive"] } +zerocopy = { version = "0.8.17", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 69fa3a24fce..603fc88e2ba 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.27", features = ["derive"] } +clap = { version = "4.5.28", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" @@ -18,7 +18,7 @@ syn = { version = "2.0.98", features = ["full", "extra-traits", "visit", "visit- walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.12.1", features = ["v4"] } +uuid = { version = "1.13.1", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index fc88b3c122f..800da9eb3c4 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,7 +10,7 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.27", features = ["derive", "string"] } +clap = { version = "4.5.28", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 8e465ce3563..f64c44713c0 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,13 +17,13 @@ bench = false [dependencies] bincode = "1.2.1" -clap = { version = "4.5.27", features = ["derive", "string"] } +clap = { version = "4.5.28", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.138" thiserror = "2.0.11" -zerocopy = { version = "0.8.14" } +zerocopy = { version = "0.8.17" } [lints] workspace = true diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index b75f490b7b0..a4cfa69074f 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,7 +10,7 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.27", features = ["derive", "string"] } +clap = { version = "4.5.28", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 0c15b57ef12..f3defb4e95d 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -17,7 +17,7 @@ base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.8.0" crc64 = "2.0.0" -derive_more = { version = "1.0.0", default-features = false, features = ["from", "display"] } +derive_more = { version = "2.0.1", default-features = false, features = ["from", "display"] } displaydoc = "0.2.5" event-manager = "0.4.0" gdbstub = { version = "0.7.3", optional = true } @@ -44,7 +44,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.14" } +zerocopy = { version = "0.8.17" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 9bd3bb9c5d4964b05518529f1b73cd09eccc399e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Feb 2025 13:51:34 +0000 Subject: [PATCH 214/464] refactor: derive `Debug` for `jailer::env::Env` Replaces a manual impl that was already missing some fields because they were added to the struct after the impl was written. Signed-off-by: Patrick Roy --- src/jailer/src/env.rs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index a0c37eac540..6d8b26c0361 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -3,13 +3,13 @@ use std::ffi::{CString, OsString}; use std::fs::{self, canonicalize, read_to_string, File, OpenOptions, Permissions}; +use std::io; use std::io::Write; use std::os::unix::fs::PermissionsExt; use std::os::unix::io::AsRawFd; use std::os::unix::process::CommandExt; use std::path::{Component, Path, PathBuf}; use std::process::{exit, id, Command, Stdio}; -use std::{fmt, io}; use utils::arg_parser::UtilsArgParserError::MissingValue; use utils::time::{get_time_us, ClockType}; @@ -114,6 +114,7 @@ enum UserfaultfdParseError { NotFound, } +#[derive(Debug)] pub struct Env { id: String, chroot_dir: PathBuf, @@ -132,26 +133,6 @@ pub struct Env { uffd_dev_minor: Option, } -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Env") - .field("id", &self.id) - .field("chroot_dir", &self.chroot_dir) - .field("exec_file_path", &self.exec_file_path) - .field("uid", &self.uid) - .field("gid", &self.gid) - .field("netns", &self.netns) - .field("daemonize", &self.daemonize) - .field("new_pid_ns", &self.new_pid_ns) - .field("start_time_us", &self.start_time_us) - .field("jailer_cpu_time_us", &self.jailer_cpu_time_us) - .field("extra_args", &self.extra_args) - .field("cgroups", &self.cgroup_conf) - .field("resource_limits", &self.resource_limits) - .finish() - } -} - impl Env { pub fn new( arguments: &arg_parser::Arguments, From c1cc05841f3f7057e3a220fd8714f80397473480 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Feb 2025 14:26:36 +0000 Subject: [PATCH 215/464] fix: compute jailer cpu time without underflow The jailer wishes to compute the CPU time it spents before exec-ing into Firecracker, so that it can be passed to Firecracker's `parent-cpu-us` flag and emitted as a metric. The CLOCK_PROCESS_CPUTIME_ID is reset on every fork() call, so we need to stitch together the different values from before the first fork, and then between each consecutive fork. However, we also need to account for the scenarios that we do not fork() at all (no daemonization). Now, this all goes slightly wrong because we want to exclude the time spent the call to Env::run() from the reported time (note that inside the jailer, this is only the time spent parsing arguments, but if a user ended up exec()-ing into the jailer, it would also include the time from prior to calling exec(), which makes sense to exclude). So we grab the value of CLOCK_PROCESS_CPUTIME_ID right after parsing arguments, and subtract it at the end. Sadly, in the case of daemonization, we subtract it not from the total amount of time spent in the jailer, but rather from the time spent since the final fork(). This works out if the time spent since the last fork was greater than the time spent parsing arguments, but if not, we have an integer underflow on our hands. Now, this is only a problem in debug builds, and in release builds, we underflow, and then _over_flow again during the next addition of the underflowed value to jailer_cpu_time_us, and Firecracker even seens a sane value for parent_time_cpu_us. But in debug builds, we panic. Fix this by breaking the subtraction and addition into two separate statements, to avoid relying on the double over-/underflow Closes #5033 Fixes: 68ab56eb242a Signed-off-by: Patrick Roy --- CHANGELOG.md | 5 +++++ src/jailer/src/env.rs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544b5a41924..2c0de0f13aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,11 @@ and this project adheres to balloon device is inflated post UFFD-backed snapshot restore, Firecracker now causes `remove` UFFD messages to be sent to the UFFD handler. Previously, no such message would be sent. +- [#5034](https://github.com/firecracker-microvm/firecracker/pull/5034): Fix an + integer underflow in the jailer when computing the value it passes to + Firecracker's `--parent-cpu-time-us` values, which caused development builds + of Firecracker to crash (but production builds were unaffected as underflows + do not panic in release mode). ## [1.10.1] diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index 6d8b26c0361..e6b0a7d9025 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -696,7 +696,8 @@ impl Env { } // Compute jailer's total CPU time up to the current time. - self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu) - self.start_time_cpu_us; + self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu); + self.jailer_cpu_time_us -= self.start_time_cpu_us; // Reset process start time. self.start_time_cpu_us = 0; From c96a1c9701fdb6be87e712e705015ed76778ed59 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Feb 2025 14:41:35 +0000 Subject: [PATCH 216/464] fix: stop double counting jailer time in process_startup_time_cpu_us In `report_cpu_start_time()`, Firecracker computers the CPU time it took until the API socket was available as CLOCK_PROCESS_CPUTIME_ID - cpu_start_time + jailer_time However, here `cpu_start_time` is always zero currently (it's the value the jailer passes via `--cpu-start-time`), and in the case where the jailer exec()s into Firecracker (without prior fork() or clone()), this is wrong: CLOCK_PROCESS_CPUTIME_ID will now be the CPU time since the _jailer_ process started, and thus adding the jailer_time to it is nonsense. This all works out if we set cpu_start_time to be the CPU time right before we exec() into Firecracker: If we did not fork(), then it will cause the calculation above to correctly discard all time before exec()-ing into Firecracker (before re-adding specifically the time spent in the jailer). If we _did_ fork(), then it will be approximately zero, and thus preserve the current semantics (as the jailer time will only be the time _until_ we did the last fork(), and CLOCK_PROCESS_CPUTIME_ID will only be the absolute CPU time _since_ the last fork()). Signed-off-by: Patrick Roy --- src/jailer/src/env.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index e6b0a7d9025..cb8646c0445 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -476,7 +476,10 @@ impl Env { Command::new(chroot_exec_file) .args(["--id", &self.id]) .args(["--start-time-us", &self.start_time_us.to_string()]) - .args(["--start-time-cpu-us", &self.start_time_cpu_us.to_string()]) + .args([ + "--start-time-cpu-us", + &get_time_us(ClockType::ProcessCpu).to_string(), + ]) .args(["--parent-cpu-time-us", &self.jailer_cpu_time_us.to_string()]) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) @@ -698,8 +701,6 @@ impl Env { // Compute jailer's total CPU time up to the current time. self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu); self.jailer_cpu_time_us -= self.start_time_cpu_us; - // Reset process start time. - self.start_time_cpu_us = 0; // If specified, exec the provided binary into a new PID namespace. if self.new_pid_ns { From 0975cd47cbe956e577f8bcd39919cdbb23ae1220 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Feb 2025 15:15:52 +0000 Subject: [PATCH 217/464] refactor: clarify computation of jailer_cpu_time_us The components that go into the calculation are 1. Exclude thing before calling Env::new() (including potential time spent in a parent of the jailer itself that ended up exec()-ing 2. The time up until a potential fork() for daemonization 3. The time spent in each temporary process during triple-fork()ing Signed-off-by: Patrick Roy --- src/jailer/src/env.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index cb8646c0445..bf75802ebe7 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -645,11 +645,10 @@ impl Env { self.mknod_and_own_dev(DEV_UFFD_PATH, DEV_UFFD_MAJOR, minor)?; } + self.jailer_cpu_time_us = get_time_us(ClockType::ProcessCpu) - self.start_time_cpu_us; + // Daemonize before exec, if so required (when the dev_null variable != None). if let Some(dev_null) = dev_null { - // Meter CPU usage before fork() - self.jailer_cpu_time_us = get_time_us(ClockType::ProcessCpu); - // We follow the double fork method to daemonize the jailer referring to // https://0xjet.github.io/3OHA/2022/04/11/post.html // setsid() will fail if the calling process is a process group leader. @@ -672,7 +671,7 @@ impl Env { .into_empty_result() .map_err(JailerError::SetSid)?; - // Meter CPU usage before fork() + // Meter CPU usage after first fork() self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu); // Daemons should not have controlling terminals. @@ -696,11 +695,10 @@ impl Env { dup2(dev_null.as_raw_fd(), STDIN_FILENO)?; dup2(dev_null.as_raw_fd(), STDOUT_FILENO)?; dup2(dev_null.as_raw_fd(), STDERR_FILENO)?; - } - // Compute jailer's total CPU time up to the current time. - self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu); - self.jailer_cpu_time_us -= self.start_time_cpu_us; + // Meter CPU usage after second fork() + self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu); + } // If specified, exec the provided binary into a new PID namespace. if self.new_pid_ns { From 561068a9ff659d04786b38fe697fc64175cbbaff Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 12 Feb 2025 13:51:35 +0000 Subject: [PATCH 218/464] fix: fail physical counter test if phy counter reg isn't in snapshot Right now the test would pass on stock AL kernels, because without the commits from 6.4 [1] backported the CNTPCT_EL0 register won't even be included in the snapshot, and thus the assert is never reached. Fix this by failing the test if the register isnt found. [1]: https://lore.kernel.org/all/20230330174800.2677007-8-maz@kernel.org/ Fixes: 525e68639d18 Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_snapshot_basic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 875ef77dbaf..6fe41f4d5a6 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -552,7 +552,7 @@ def test_vmgenid(guest_kernel_linux_6_1, rootfs, microvm_factory, snapshot_type) platform.machine() != "aarch64" or global_props.host_linux_version_tpl < (6, 4), reason="This is aarch64 specific test and should only be run on 6.4 and later kernels", ) -def test_physical_couter_reset_aarch64(uvm_nano): +def test_physical_counter_reset_aarch64(uvm_nano): """ Test that the CNTPCT_EL0 register is reset on VM boot. We assume the smallest VM will not consume more than @@ -597,3 +597,6 @@ def test_physical_couter_reset_aarch64(uvm_nano): reg_id, reg_value = parts if reg_id == cntpct_el0: assert int(reg_value, 16) < max_value + break + else: + raise RuntimeError("Did not find CNTPCT_EL0 register in snapshot") From d1badbb3029cbbd75efc2ec4f77c43ee93bdf5a6 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Feb 2025 11:00:28 +0000 Subject: [PATCH 219/464] do not fail balloon test if deflate_oom is false and guest crashes If we set deflate_on_oom to False, and then induce an out of memory condition, then we're really only testing how well the guest can handle oom conditions. Do not fail the test if the guest responds to OOM by shutting down though. Signed-off-by: Patrick Roy --- .../functional/test_balloon.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index 41a790190de..f222c46aa0b 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -207,12 +207,20 @@ def test_deflate_on_oom(uvm_plain_any, deflate_on_oom): balloon_size_before = test_microvm.api.balloon_stats.get().json()["actual_mib"] make_guest_dirty_memory(test_microvm.ssh, 128) - balloon_size_after = test_microvm.api.balloon_stats.get().json()["actual_mib"] - print(f"size before: {balloon_size_before} size after: {balloon_size_after}") - if deflate_on_oom: - assert balloon_size_after < balloon_size_before, "Balloon did not deflate" + try: + balloon_size_after = test_microvm.api.balloon_stats.get().json()["actual_mib"] + except ConnectionError: + assert ( + not deflate_on_oom + ), "Guest died even though it should have deflated balloon to alleviate memory pressure" + + test_microvm.mark_killed() else: - assert balloon_size_after >= balloon_size_before, "Balloon deflated" + print(f"size before: {balloon_size_before} size after: {balloon_size_after}") + if deflate_on_oom: + assert balloon_size_after < balloon_size_before, "Balloon did not deflate" + else: + assert balloon_size_after >= balloon_size_before, "Balloon deflated" # pylint: disable=C0103 From 5cf6525015bbb1a9671671ee44954bbc153de738 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Feb 2025 16:13:09 +0000 Subject: [PATCH 220/464] add `restart_syscall(2)` to seccomp allowlist This syscall is issued transparently by the linux kernel when timing-related syscalls (such as nanosleep) get interrupted, for example because of SIGSTOP. Signed-off-by: Patrick Roy --- resources/seccomp/aarch64-unknown-linux-musl.json | 12 ++++++++++++ resources/seccomp/x86_64-unknown-linux-musl.json | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/resources/seccomp/aarch64-unknown-linux-musl.json b/resources/seccomp/aarch64-unknown-linux-musl.json index 10abb9dc9ed..e618536c950 100644 --- a/resources/seccomp/aarch64-unknown-linux-musl.json +++ b/resources/seccomp/aarch64-unknown-linux-musl.json @@ -444,6 +444,10 @@ { "syscall": "recvmsg", "comment": "Used by vhost-user frontend to read response from the backend" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] }, @@ -726,6 +730,10 @@ { "syscall": "sched_yield", "comment": "Used by the rust standard library in std::sync::mpmc. Firecracker uses mpsc channels from this module for inter-thread communication" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] }, @@ -1009,6 +1017,10 @@ { "syscall": "sendmsg", "comment": "Used by vhost-user frontend to communicate with the backend" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] } diff --git a/resources/seccomp/x86_64-unknown-linux-musl.json b/resources/seccomp/x86_64-unknown-linux-musl.json index 5a70f4c01d1..4920b68bacc 100644 --- a/resources/seccomp/x86_64-unknown-linux-musl.json +++ b/resources/seccomp/x86_64-unknown-linux-musl.json @@ -452,6 +452,10 @@ { "syscall": "recvmsg", "comment": "Used by vhost-user frontend to read response from the backend" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] }, @@ -734,6 +738,10 @@ { "syscall": "sched_yield", "comment": "Used by the rust standard library in std::sync::mpmc. Firecracker uses mpsc channels from this module for inter-thread communication" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] }, @@ -1125,6 +1133,10 @@ { "syscall": "sendmsg", "comment": "Used by vhost-user frontend to communicate with the backend" + }, + { + "syscall": "restart_syscall", + "comment": "automatically issued by the kernel when specific timing-related syscalls (e.g. nanosleep) get interrupted by SIGSTOP" } ] } From d6a14fb04003cd1df8a064384ed02f1561d2d23a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Feb 2025 16:22:35 +0000 Subject: [PATCH 221/464] test: explicitly exclude `restart_syscall` from seccomp analysis This syscall is inserted at runtime by the linux kernel, and thus not actually present in our binary. The static analysis tool thus correctly marks it as unused. Introduce an allowlist of syscalls that are ignored by the static analysis tool to deal with this. Signed-off-by: Patrick Roy --- tests/framework/static_analysis.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/framework/static_analysis.py b/tests/framework/static_analysis.py index fd249f59b85..f75f938a27a 100644 --- a/tests/framework/static_analysis.py +++ b/tests/framework/static_analysis.py @@ -584,6 +584,12 @@ def load_seccomp_rules(seccomp_path: Path): return allowlist +KNOWN_SUPERFLUOUS_RULES = { + # This syscall is inserted at runtime by the linux kernel, and thus not actually present in our binary. + "restart_syscall": [{}] +} + + def determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls): """Based on the given list of syscall determined through static analysis, compute which of the given seccomp rules are redundant. By 'redundant' we here mean that no syscall that would match @@ -596,6 +602,12 @@ def determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls): for syscall, rules in seccomp_rules.items(): for allowed_arguments in rules: + if ( + syscall in KNOWN_SUPERFLUOUS_RULES + and allowed_arguments in KNOWN_SUPERFLUOUS_RULES[syscall] + ): + continue + # A rule is not needed if for all actual invocation of the syscall the rule governs, # the rule does not match. # Here, we determine "does not match" as "the rule specifies some value for an argument of the syscall to be From e6ceb57d6a0add70006e8df317dd931496e38569 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 14 Feb 2025 13:26:56 +0000 Subject: [PATCH 222/464] test: catch correct exception in memory.py The access to the `firecracker_pid` property causes a read to the vm's pid file. This means that in the scenario where the VM is already dead by the time the monitor starts running, we won't get a `NoSuchProcess` error, we potentially get a `FileNotFoundError` (if the jail is already cleaned up). Thus, to avoid spurious failures, also catch `FileNotFoundError`. We leave the catch for `NoSuchProcess` error in case a VM exits between reading the pid file and the call to the`psutils.Process` constructor (race condition). Signed-off-by: Patrick Roy --- tests/host_tools/memory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/host_tools/memory.py b/tests/host_tools/memory.py index 690cda38701..93380a9321d 100644 --- a/tests/host_tools/memory.py +++ b/tests/host_tools/memory.py @@ -62,7 +62,7 @@ def run(self): guest_mem_bytes = self._vm.mem_size_bytes try: ps = psutil.Process(self._vm.firecracker_pid) - except psutil.NoSuchProcess: + except (psutil.NoSuchProcess, FileNotFoundError): return while not self._should_stop: try: From 5a378ced496f912a4d5a75aa15d7c296b2829676 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 14 Feb 2025 13:28:56 +0000 Subject: [PATCH 223/464] devtool: fix permissions on .python/ after cmd_sandbox Running the sandbox command leaves the .ipython folder as owned by root. Fix this up after exiting so that its can be accesses un-privileged after docker exits (I have a git pre-commit hook that tries to stash all unstaged changes, and it always chokes on this folder). Signed-off-by: Patrick Roy --- tools/devtool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 1e53cc6c6bb..7bf8d4ad6fb 100755 --- a/tools/devtool +++ b/tools/devtool @@ -228,7 +228,7 @@ cmd_fix_perms() { run_devctr \ --workdir "$CTR_FC_ROOT_DIR" \ -- \ - chown -f -R "$(id -u):$(id -g)" "$CTR_FC_BUILD_DIR" "$CTR_TEST_RESULTS_DIR" "$CTR_CI_ARTIFACTS_PATH" + chown -f -R "$(id -u):$(id -g)" "$CTR_FC_BUILD_DIR" "$CTR_TEST_RESULTS_DIR" "$CTR_CI_ARTIFACTS_PATH" $@ } # Builds the development container from its Dockerfile. @@ -890,6 +890,7 @@ cmd_sandbox() { cmd_build --release ensure_ci_artifacts cmd_sh "tmux new env PYTEST_ADDOPTS=--pdbcls=IPython.terminal.debugger:TerminalPdb PYTHONPATH=tests IPYTHONDIR=\$PWD/.ipython ipython -i ./tools/sandbox.py $@" + cmd_fix_perms ".ipython" } cmd_sandbox_native() { From 6521be587031f52fb661f2991dc71e1b6bd9ba09 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 14 Feb 2025 13:53:07 +0000 Subject: [PATCH 224/464] test: stop printing host dmesg on test failure Because we're storing dmesg in a local variable, if an exception occurs while killing a microvm, python will end up printing the entirety of the host dmesg output to stderr, because it dumps local variables as part of the backtrace. This is fine in CI because instances are shortlived, but when running tests locally, it takes my terminal multiple minutes to catch up with the amount of text that ends up being printed. Fix this by not storing dmesg in a local variable anymore, and instead inline it to its only use-site. Signed-off-by: Patrick Roy --- tests/conftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 552ba25c4ef..e3aea3a8dfa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -336,11 +336,12 @@ def microvm_factory(request, record_property, results_dir, netns_factory): # if the test failed, save important files from the root of the uVM into `test_results` for troubleshooting report = request.node.stash[PHASE_REPORT_KEY] if "call" in report and report["call"].failed: - dmesg = utils.run_cmd(["dmesg", "-dPx"]) for uvm in uvm_factory.vms: uvm_data = results_dir / uvm.id uvm_data.mkdir() - uvm_data.joinpath("host-dmesg.log").write_text(dmesg.stdout) + uvm_data.joinpath("host-dmesg.log").write_text( + utils.run_cmd(["dmesg", "-dPx"]).stdout + ) shutil.copy(f"/firecracker/build/img/{platform.machine()}/id_rsa", uvm_data) uvm_root = Path(uvm.chroot()) From 07ce762b9a404834f8296349279f81a6914a4a95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:15:37 +0000 Subject: [PATCH 225/464] build(deps): Bump the firecracker group with 6 updates Bumps the firecracker group with 6 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.17` | `0.8.18` | | [clap](https://github.com/clap-rs/clap) | `4.5.28` | `4.5.29` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.13` | `1.2.14` | | [clap_builder](https://github.com/clap-rs/clap) | `4.5.27` | `4.5.29` | | [equivalent](https://github.com/indexmap-rs/equivalent) | `1.0.1` | `1.0.2` | | [toml_edit](https://github.com/toml-rs/toml) | `0.22.23` | `0.22.24` | Updates `zerocopy` from 0.8.17 to 0.8.18 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.17...v0.8.18) Updates `clap` from 4.5.28 to 4.5.29 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.28...clap_complete-v4.5.29) Updates `cc` from 1.2.13 to 1.2.14 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.13...cc-v1.2.14) Updates `clap_builder` from 4.5.27 to 4.5.29 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.27...v4.5.29) Updates `equivalent` from 1.0.1 to 1.0.2 - [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2) Updates `toml_edit` from 0.22.23 to 0.22.24 - [Commits](https://github.com/toml-rs/toml/compare/v0.22.23...v0.22.24) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: equivalent dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: toml_edit dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 40 +++++++++++++++--------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 4 +-- src/snapshot-editor/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23367c3a153..2826568ba8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.11", "vm-memory", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.13" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" +checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" dependencies = [ "jobserver", "libc", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.28" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" +checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" dependencies = [ "anstream", "anstyle", @@ -573,9 +573,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -1096,7 +1096,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.0", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -1135,7 +1135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -1233,7 +1233,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.11", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -1422,9 +1422,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.23" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", @@ -1631,7 +1631,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.17", + "zerocopy 0.8.18", ] [[package]] @@ -1817,11 +1817,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" dependencies = [ - "zerocopy-derive 0.8.17", + "zerocopy-derive 0.8.18", ] [[package]] @@ -1837,9 +1837,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index ac4bbaaa47d..a07e5607ae3 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.11" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.17", features = ["derive"] } +zerocopy = { version = "0.8.18", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 603fc88e2ba..c40e060677f 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.28", features = ["derive"] } +clap = { version = "4.5.29", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 800da9eb3c4..0eb8da92d29 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,7 +10,7 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.28", features = ["derive", "string"] } +clap = { version = "4.5.29", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" log-instrument = { path = "../log-instrument", optional = true } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index f64c44713c0..f69f55b84ac 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,13 +17,13 @@ bench = false [dependencies] bincode = "1.2.1" -clap = { version = "4.5.28", features = ["derive", "string"] } +clap = { version = "4.5.29", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.169" serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.138" thiserror = "2.0.11" -zerocopy = { version = "0.8.17" } +zerocopy = { version = "0.8.18" } [lints] workspace = true diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index a4cfa69074f..0019afda741 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,7 +10,7 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.28", features = ["derive", "string"] } +clap = { version = "4.5.29", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index f3defb4e95d..035e28505a3 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -44,7 +44,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.17" } +zerocopy = { version = "0.8.18" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 2167247b5572a45ba9d920cd5e70fc9d02249b41 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 18 Feb 2025 09:47:47 +0000 Subject: [PATCH 226/464] fix: handle overflow when computing mmap offset during restore Since we dropped the explicit offset field from the snapshot file, we are implicit computing it as "sum of sizes of all preceding regions". If the snapshot file is corrupted, it can describe regions whose sum exceeds u64::MAX. Fix this by adding overflow checks and returning an error in case of overflows We also error out if it exceeds i64::MAX as the offset argument to mmap(2) is a signed 64 bit integer value. Fixes: d8358055d4b2 Signed-off-by: Patrick Roy --- src/vmm/src/vstate/memory.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index b89de3453c2..23ce07d06b9 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -52,6 +52,8 @@ pub enum MemoryError { Memfd(memfd::Error), /// Cannot resize memfd file: {0} MemfdSetLen(std::io::Error), + /// Total sum of memory regions exceeds largest possible file offset + OffsetTooLarge, } /// Defines the interface for snapshotting memory. @@ -188,7 +190,13 @@ impl GuestMemoryExtension for GuestMemoryMmap { builder = builder.with_file_offset(file_offset); } - offset += size as u64; + offset = match offset.checked_add(size as u64) { + None => return Err(MemoryError::OffsetTooLarge), + Some(new_off) if new_off >= i64::MAX as u64 => { + return Err(MemoryError::OffsetTooLarge) + } + Some(new_off) => new_off, + }; GuestRegionMmap::new( builder.build().map_err(MemoryError::MmapRegionError)?, From 51bbc777e982d956e198babd027273c63fdde90f Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 20 Feb 2025 11:52:31 +0000 Subject: [PATCH 227/464] fix(jailer): Make "init" in new PID NS a session leader https://man7.org/linux/man-pages/man7/pid_namespaces.7.html > A process in an ancestor namespace can send signals to the "init" > process of a child PID namespace only if the "init" process has > established a handelr for that signal. Firecracker (i.e. the "init" process of the new PID namespace) sets up handlers for some signals including SIGHUP and jailer exits soon after spawning firecracker into the new PID namespace. If the jailer process is a session leader and its exit happens after firecracker configures the signal handlers, SIGHUP will be sent to firecracker and be caught by the handler unexpectedly. In order to avoid the above issue, if jailer is a session leader, creates a new session and makes the child process (i.e. firecracker) become the leader of the new session to not get SIGHUP on the exit of jailer. Note that this is the case only if `--daemonize` is not passed. This is because we use the double fork method to daemonize, making itself not a session leader. Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 3 +++ src/jailer/src/env.rs | 42 +++++++++++++++++++++++++++++++++++++++++- src/jailer/src/main.rs | 4 ++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c0de0f13aa..a7bf7d4c014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,9 @@ and this project adheres to Firecracker's `--parent-cpu-time-us` values, which caused development builds of Firecracker to crash (but production builds were unaffected as underflows do not panic in release mode). +- [#5045](https://github.com/firecracker-microvm/firecracker/pull/5045): Fixed + an issue where firecracker intermittently receives SIGHUP when using jailer + with `--new-pid-ns` but without `--daemonize`. ## [1.10.1] diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index bf75802ebe7..61cd121b0dc 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -330,12 +330,52 @@ impl Env { } fn exec_into_new_pid_ns(&mut self, chroot_exec_file: PathBuf) -> Result<(), JailerError> { + // https://man7.org/linux/man-pages/man7/pid_namespaces.7.html + // > a process in an ancestor namespace can send signals to the "init" process of a child + // > PID namespace only if the "init" process has established a handler for that signal. + // + // Firecracker (i.e. the "init" process of the new PID namespace) sets up handlers for some + // signals including SIGHUP and jailer exits soon after spawning firecracker into a new PID + // namespace. If the jailer process is a session leader and its exit happens after + // firecracker configures the signal handlers, SIGHUP will be sent to firecracker and be + // caught by the handler unexpectedly. + // + // In order to avoid the above issue, if jailer is a session leader, creates a new session + // and makes the child process (i.e. firecracker) become the leader of the new session to + // not get SIGHUP on the exit of jailer. + + // Check whether jailer is a session leader or not before clone(). + // Note that, if `--daemonize` is passed, jailer is always not a session leader. This is + // because we use the double fork method, making itself not a session leader. + let is_session_leader = match self.daemonize { + true => false, + false => { + // SAFETY: Safe because it doesn't take any input parameters. + let sid = SyscallReturnCode(unsafe { libc::getsid(0) }) + .into_result() + .map_err(JailerError::GetSid)?; + // SAFETY: Safe because it doesn't take any input parameters. + let ppid = SyscallReturnCode(unsafe { libc::getpid() }) + .into_result() + .map_err(JailerError::GetPid)?; + sid == ppid + } + }; + // Duplicate the current process. The child process will belong to the previously created // PID namespace. The current process will not be moved into the newly created namespace, // but its first child will assume the role of init(1) in the new namespace. let pid = clone(std::ptr::null_mut(), libc::CLONE_NEWPID)?; match pid { - 0 => Err(JailerError::Exec(self.exec_command(chroot_exec_file))), + 0 => { + if is_session_leader { + // SAFETY: Safe bacause it doesn't take any input parameters. + SyscallReturnCode(unsafe { libc::setsid() }) + .into_empty_result() + .map_err(JailerError::SetSid)?; + } + Err(JailerError::Exec(self.exec_command(chroot_exec_file))) + } child_pid => { // Save the PID of the process running the exec file provided // inside .pid file. diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs index 4e00c14762a..fc7ac216599 100644 --- a/src/jailer/src/main.rs +++ b/src/jailer/src/main.rs @@ -85,6 +85,10 @@ pub enum JailerError { FromBytesWithNul(std::ffi::FromBytesWithNulError), #[error("Failed to get flags from fd: {0}")] GetOldFdFlags(io::Error), + #[error("Failed to get PID (getpid): {0}")] + GetPid(io::Error), + #[error("Failed to get SID (getsid): {0}")] + GetSid(io::Error), #[error("Invalid gid: {0}")] Gid(String), #[error("Invalid instance ID: {0}")] From 9af26f1109d088ba216a02b839afc751f72710a1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 12:13:40 +0000 Subject: [PATCH 228/464] refactor: move arch specific code from vm.rs into modules Follow a similar approach we already take for the vcpu module, where all the architecture specific stuff is inside aarch64/x86_64 modules, keeping only the common code in the `vm` module. No functional change intended. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vm.rs | 464 ------------------------------- src/vmm/src/vstate/vm/aarch64.rs | 66 +++++ src/vmm/src/vstate/vm/mod.rs | 199 +++++++++++++ src/vmm/src/vstate/vm/x86_64.rs | 221 +++++++++++++++ 4 files changed, 486 insertions(+), 464 deletions(-) delete mode 100644 src/vmm/src/vstate/vm.rs create mode 100644 src/vmm/src/vstate/vm/aarch64.rs create mode 100644 src/vmm/src/vstate/vm/mod.rs create mode 100644 src/vmm/src/vstate/vm/x86_64.rs diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs deleted file mode 100644 index 19ca0b2a76c..00000000000 --- a/src/vmm/src/vstate/vm.rs +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the THIRD-PARTY file. - -#[cfg(target_arch = "x86_64")] -use std::fmt; - -#[cfg(target_arch = "x86_64")] -use kvm_bindings::{ - kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE, - KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, -}; -use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; -// use kvm_ioctls::{Kvm, VmFd}; -use kvm_ioctls::VmFd; -use serde::{Deserialize, Serialize}; - -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::gic::GICDevice; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::gic::GicState; -#[cfg(target_arch = "x86_64")] -use crate::utils::u64_to_usize; -use crate::vstate::kvm::Kvm; -use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; - -/// Errors associated with the wrappers over KVM ioctls. -/// Needs `rustfmt::skip` to make multiline comments work -#[rustfmt::skip] -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] -pub enum VmError { - /// Cannot set the memory regions: {0} - SetUserMemoryRegion(kvm_ioctls::Error), - #[cfg(target_arch = "aarch64")] - /// Error creating the global interrupt controller: {0} - VmCreateGIC(crate::arch::aarch64::gic::GicError), - /// Cannot open the VM file descriptor: {0} - VmFd(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm pit state: {0} - VmGetPit2(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm clock: {0} - VmGetClock(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm irqchip: {0} - VmGetIrqChip(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm pit state: {0} - VmSetPit2(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm clock: {0} - VmSetClock(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm irqchip: {0} - VmSetIrqChip(kvm_ioctls::Error), - /// Cannot configure the microvm: {0} - VmSetup(kvm_ioctls::Error), - #[cfg(target_arch = "aarch64")] - /// Failed to save the VM's GIC state: {0} - SaveGic(crate::arch::aarch64::gic::GicError), - #[cfg(target_arch = "aarch64")] - /// Failed to restore the VM's GIC state: {0} - RestoreGic(crate::arch::aarch64::gic::GicError), -} - -/// Error type for [`Vm::restore_state`] -#[allow(missing_docs)] -#[cfg(target_arch = "x86_64")] -#[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)] -pub enum RestoreStateError { - /// Set PIT2 error: {0} - SetPit2(kvm_ioctls::Error), - /// Set clock error: {0} - SetClock(kvm_ioctls::Error), - /// Set IrqChipPicMaster error: {0} - SetIrqChipPicMaster(kvm_ioctls::Error), - /// Set IrqChipPicSlave error: {0} - SetIrqChipPicSlave(kvm_ioctls::Error), - /// Set IrqChipIoAPIC error: {0} - SetIrqChipIoAPIC(kvm_ioctls::Error), - /// VM error: {0} - VmError(VmError), -} - -/// Error type for [`Vm::restore_state`] -#[cfg(target_arch = "aarch64")] -#[derive(Debug, thiserror::Error, displaydoc::Display)] -pub enum RestoreStateError { - /// {0} - GicError(crate::arch::aarch64::gic::GicError), - /// {0} - VmError(VmError), -} - -/// A wrapper around creating and using a VM. -#[derive(Debug)] -pub struct Vm { - fd: VmFd, - - // Arm specific fields. - // On aarch64 we need to keep around the fd obtained by creating the VGIC device. - #[cfg(target_arch = "aarch64")] - irqchip_handle: Option, -} - -/// Contains Vm functions that are usable across CPU architectures -impl Vm { - /// Create a new `Vm` struct. - pub fn new(kvm: &Kvm) -> Result { - // Create fd for interacting with kvm-vm specific functions. - let vm_fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; - - #[cfg(target_arch = "aarch64")] - { - Ok(Vm { - fd: vm_fd, - irqchip_handle: None, - }) - } - - #[cfg(target_arch = "x86_64")] - { - Ok(Vm { fd: vm_fd }) - } - } - - /// Initializes the guest memory. - pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { - self.set_kvm_memory_regions(guest_mem)?; - #[cfg(target_arch = "x86_64")] - self.fd - .set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) - .map_err(VmError::VmSetup)?; - - Ok(()) - } - - pub(crate) fn set_kvm_memory_regions( - &self, - guest_mem: &GuestMemoryMmap, - ) -> Result<(), VmError> { - guest_mem - .iter() - .zip(0u32..) - .try_for_each(|(region, slot)| { - let flags = if region.bitmap().is_some() { - KVM_MEM_LOG_DIRTY_PAGES - } else { - 0 - }; - - let memory_region = kvm_userspace_memory_region { - slot, - guest_phys_addr: region.start_addr().raw_value(), - memory_size: region.len(), - // It's safe to unwrap because the guest address is valid. - userspace_addr: guest_mem.get_host_address(region.start_addr()).unwrap() as u64, - flags, - }; - - // SAFETY: Safe because the fd is a valid KVM file descriptor. - unsafe { self.fd.set_user_memory_region(memory_region) } - }) - .map_err(VmError::SetUserMemoryRegion)?; - Ok(()) - } - - /// Gets a reference to the kvm file descriptor owned by this VM. - pub fn fd(&self) -> &VmFd { - &self.fd - } -} - -#[cfg(target_arch = "aarch64")] -impl Vm { - /// Creates the GIC (Global Interrupt Controller). - pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), VmError> { - self.irqchip_handle = Some( - crate::arch::aarch64::gic::create_gic(&self.fd, vcpu_count.into(), None) - .map_err(VmError::VmCreateGIC)?, - ); - Ok(()) - } - - /// Gets a reference to the irqchip of the VM. - pub fn get_irqchip(&self) -> &GICDevice { - self.irqchip_handle.as_ref().expect("IRQ chip not set") - } - - /// Saves and returns the Kvm Vm state. - pub fn save_state(&self, mpidrs: &[u64]) -> Result { - Ok(VmState { - gic: self - .get_irqchip() - .save_device(mpidrs) - .map_err(VmError::SaveGic)?, - }) - } - - /// Restore the KVM VM state - /// - /// # Errors - /// - /// When [`GICDevice::restore_device`] errors. - pub fn restore_state( - &mut self, - mpidrs: &[u64], - state: &VmState, - ) -> Result<(), RestoreStateError> { - self.get_irqchip() - .restore_device(mpidrs, &state.gic) - .map_err(RestoreStateError::GicError)?; - Ok(()) - } -} - -/// Structure holding an general specific VM state. -#[cfg(target_arch = "aarch64")] -#[derive(Debug, Default, Serialize, Deserialize)] -pub struct VmState { - /// GIC state. - pub gic: GicState, -} - -#[cfg(target_arch = "x86_64")] -impl Vm { - /// Restores the KVM VM state. - /// - /// # Errors - /// - /// When: - /// - [`kvm_ioctls::VmFd::set_pit`] errors. - /// - [`kvm_ioctls::VmFd::set_clock`] errors. - /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. - /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. - /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. - pub fn restore_state(&mut self, state: &VmState) -> Result<(), RestoreStateError> { - self.fd - .set_pit2(&state.pitstate) - .map_err(RestoreStateError::SetPit2)?; - self.fd - .set_clock(&state.clock) - .map_err(RestoreStateError::SetClock)?; - self.fd - .set_irqchip(&state.pic_master) - .map_err(RestoreStateError::SetIrqChipPicMaster)?; - self.fd - .set_irqchip(&state.pic_slave) - .map_err(RestoreStateError::SetIrqChipPicSlave)?; - self.fd - .set_irqchip(&state.ioapic) - .map_err(RestoreStateError::SetIrqChipIoAPIC)?; - Ok(()) - } - - /// Creates the irq chip and an in-kernel device model for the PIT. - pub fn setup_irqchip(&self) -> Result<(), VmError> { - self.fd.create_irq_chip().map_err(VmError::VmSetup)?; - // We need to enable the emulation of a dummy speaker port stub so that writing to port 0x61 - // (i.e. KVM_SPEAKER_BASE_ADDRESS) does not trigger an exit to user space. - let pit_config = kvm_pit_config { - flags: KVM_PIT_SPEAKER_DUMMY, - ..Default::default() - }; - self.fd.create_pit2(pit_config).map_err(VmError::VmSetup) - } - - /// Saves and returns the Kvm Vm state. - pub fn save_state(&self) -> Result { - let pitstate = self.fd.get_pit2().map_err(VmError::VmGetPit2)?; - - let mut clock = self.fd.get_clock().map_err(VmError::VmGetClock)?; - // This bit is not accepted in SET_CLOCK, clear it. - clock.flags &= !KVM_CLOCK_TSC_STABLE; - - let mut pic_master = kvm_irqchip { - chip_id: KVM_IRQCHIP_PIC_MASTER, - ..Default::default() - }; - self.fd - .get_irqchip(&mut pic_master) - .map_err(VmError::VmGetIrqChip)?; - - let mut pic_slave = kvm_irqchip { - chip_id: KVM_IRQCHIP_PIC_SLAVE, - ..Default::default() - }; - self.fd - .get_irqchip(&mut pic_slave) - .map_err(VmError::VmGetIrqChip)?; - - let mut ioapic = kvm_irqchip { - chip_id: KVM_IRQCHIP_IOAPIC, - ..Default::default() - }; - self.fd - .get_irqchip(&mut ioapic) - .map_err(VmError::VmGetIrqChip)?; - - Ok(VmState { - pitstate, - clock, - pic_master, - pic_slave, - ioapic, - }) - } -} - -#[cfg(target_arch = "x86_64")] -#[derive(Default, Deserialize, Serialize)] -/// Structure holding VM kvm state. -pub struct VmState { - pitstate: kvm_pit_state2, - clock: kvm_clock_data, - // TODO: rename this field to adopt inclusive language once Linux updates it, too. - pic_master: kvm_irqchip, - // TODO: rename this field to adopt inclusive language once Linux updates it, too. - pic_slave: kvm_irqchip, - ioapic: kvm_irqchip, -} - -#[cfg(target_arch = "x86_64")] -impl fmt::Debug for VmState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("VmState") - .field("pitstate", &self.pitstate) - .field("clock", &self.clock) - .field("pic_master", &"?") - .field("pic_slave", &"?") - .field("ioapic", &"?") - .finish() - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - #[cfg(target_arch = "x86_64")] - use crate::snapshot::Snapshot; - use crate::test_utils::single_region_mem; - use crate::vstate::memory::GuestMemoryMmap; - - // Auxiliary function being used throughout the tests. - pub(crate) fn setup_vm() -> (Kvm, Vm) { - let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); - let vm = Vm::new(&kvm).expect("Cannot create new vm"); - (kvm, vm) - } - - // Auxiliary function being used throughout the tests. - pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm, GuestMemoryMmap) { - let (kvm, vm) = setup_vm(); - let gm = single_region_mem(mem_size); - vm.memory_init(&gm).unwrap(); - (kvm, vm, gm) - } - - #[test] - fn test_new() { - // Testing with a valid /dev/kvm descriptor. - let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); - Vm::new(&kvm).unwrap(); - } - - #[test] - fn test_vm_memory_init() { - let (_, vm) = setup_vm(); - // Create valid memory region and test that the initialization is successful. - let gm = single_region_mem(0x1000); - vm.memory_init(&gm).unwrap(); - } - - #[cfg(target_arch = "x86_64")] - #[test] - fn test_vm_save_restore_state() { - let (_, vm) = setup_vm(); - // Irqchips, clock and pitstate are not configured so trying to save state should fail. - vm.save_state().unwrap_err(); - - let (_, vm, _mem) = setup_vm_with_memory(0x1000); - vm.setup_irqchip().unwrap(); - - let vm_state = vm.save_state().unwrap(); - assert_eq!( - vm_state.pitstate.flags | KVM_PIT_SPEAKER_DUMMY, - KVM_PIT_SPEAKER_DUMMY - ); - assert_eq!(vm_state.clock.flags & KVM_CLOCK_TSC_STABLE, 0); - assert_eq!(vm_state.pic_master.chip_id, KVM_IRQCHIP_PIC_MASTER); - assert_eq!(vm_state.pic_slave.chip_id, KVM_IRQCHIP_PIC_SLAVE); - assert_eq!(vm_state.ioapic.chip_id, KVM_IRQCHIP_IOAPIC); - - let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); - vm.setup_irqchip().unwrap(); - - vm.restore_state(&vm_state).unwrap(); - } - - #[cfg(target_arch = "x86_64")] - #[test] - fn test_vm_save_restore_state_bad_irqchip() { - use kvm_bindings::KVM_NR_IRQCHIPS; - - let (_, vm, _mem) = setup_vm_with_memory(0x1000); - vm.setup_irqchip().unwrap(); - let mut vm_state = vm.save_state().unwrap(); - - let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); - vm.setup_irqchip().unwrap(); - - // Try to restore an invalid PIC Master chip ID - let orig_master_chip_id = vm_state.pic_master.chip_id; - vm_state.pic_master.chip_id = KVM_NR_IRQCHIPS; - vm.restore_state(&vm_state).unwrap_err(); - vm_state.pic_master.chip_id = orig_master_chip_id; - - // Try to restore an invalid PIC Slave chip ID - let orig_slave_chip_id = vm_state.pic_slave.chip_id; - vm_state.pic_slave.chip_id = KVM_NR_IRQCHIPS; - vm.restore_state(&vm_state).unwrap_err(); - vm_state.pic_slave.chip_id = orig_slave_chip_id; - - // Try to restore an invalid IOPIC chip ID - vm_state.ioapic.chip_id = KVM_NR_IRQCHIPS; - vm.restore_state(&vm_state).unwrap_err(); - } - - #[cfg(target_arch = "x86_64")] - #[test] - fn test_vmstate_serde() { - let mut snapshot_data = vec![0u8; 10000]; - - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - vm.setup_irqchip().unwrap(); - let state = vm.save_state().unwrap(); - Snapshot::serialize(&mut snapshot_data.as_mut_slice(), &state).unwrap(); - let restored_state: VmState = Snapshot::deserialize(&mut snapshot_data.as_slice()).unwrap(); - - vm.restore_state(&restored_state).unwrap(); - } - - #[test] - fn test_set_kvm_memory_regions() { - let (_, vm) = setup_vm(); - - let gm = single_region_mem(0x1000); - let res = vm.set_kvm_memory_regions(&gm); - res.unwrap(); - - // Trying to set a memory region with a size that is not a multiple of GUEST_PAGE_SIZE - // will result in error. - let gm = single_region_mem(0x10); - let res = vm.set_kvm_memory_regions(&gm); - assert_eq!( - res.unwrap_err().to_string(), - "Cannot set the memory regions: Invalid argument (os error 22)" - ); - } -} diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs new file mode 100644 index 00000000000..0925ad4d7e2 --- /dev/null +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -0,0 +1,66 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Serialize}; + +use crate::arch::aarch64::gic::GicState; +use crate::vstate::vm::VmError; +use crate::Vm; + +/// Error type for [`Vm::restore_state`] +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum RestoreStateError { + /// {0} + GicError(crate::arch::aarch64::gic::GicError), + /// {0} + VmError(VmError), +} + +impl Vm { + /// Creates the GIC (Global Interrupt Controller). + pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), VmError> { + self.irqchip_handle = Some( + crate::arch::aarch64::gic::create_gic(&self.fd, vcpu_count.into(), None) + .map_err(VmError::VmCreateGIC)?, + ); + Ok(()) + } + + /// Gets a reference to the irqchip of the VM. + pub fn get_irqchip(&self) -> &crate::arch::aarch64::gic::GICDevice { + self.irqchip_handle.as_ref().expect("IRQ chip not set") + } + + /// Saves and returns the Kvm Vm state. + pub fn save_state(&self, mpidrs: &[u64]) -> Result { + Ok(crate::vstate::vm::VmState { + gic: self + .get_irqchip() + .save_device(mpidrs) + .map_err(VmError::SaveGic)?, + }) + } + + /// Restore the KVM VM state + /// + /// # Errors + /// + /// When [`crate::arch::aarch64::gic::GICDevice::restore_device`] errors. + pub fn restore_state( + &mut self, + mpidrs: &[u64], + state: &crate::vstate::vm::VmState, + ) -> Result<(), RestoreStateError> { + self.get_irqchip() + .restore_device(mpidrs, &state.gic) + .map_err(RestoreStateError::GicError)?; + Ok(()) + } +} + +/// Structure holding an general specific VM state. +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct VmState { + /// GIC state. + pub gic: GicState, +} diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs new file mode 100644 index 00000000000..65c3ab43f74 --- /dev/null +++ b/src/vmm/src/vstate/vm/mod.rs @@ -0,0 +1,199 @@ +// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the THIRD-PARTY file. + +use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; +use kvm_ioctls::VmFd; + +#[cfg(target_arch = "aarch64")] +use crate::arch::aarch64::gic::GICDevice; +#[cfg(target_arch = "x86_64")] +use crate::utils::u64_to_usize; +use crate::vstate::kvm::Kvm; +use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; + +#[cfg(target_arch = "x86_64")] +#[path = "x86_64.rs"] +mod arch; +#[cfg(target_arch = "aarch64")] +#[path = "aarch64.rs"] +mod arch; + +pub use arch::{RestoreStateError, VmState}; + +/// Errors associated with the wrappers over KVM ioctls. +/// Needs `rustfmt::skip` to make multiline comments work +#[rustfmt::skip] +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum VmError { + /// Cannot set the memory regions: {0} + SetUserMemoryRegion(kvm_ioctls::Error), + #[cfg(target_arch = "aarch64")] + /// Error creating the global interrupt controller: {0} + VmCreateGIC(crate::arch::aarch64::gic::GicError), + /// Cannot open the VM file descriptor: {0} + VmFd(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to get KVM vm pit state: {0} + VmGetPit2(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to get KVM vm clock: {0} + VmGetClock(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to get KVM vm irqchip: {0} + VmGetIrqChip(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to set KVM vm pit state: {0} + VmSetPit2(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to set KVM vm clock: {0} + VmSetClock(kvm_ioctls::Error), + #[cfg(target_arch = "x86_64")] + /// Failed to set KVM vm irqchip: {0} + VmSetIrqChip(kvm_ioctls::Error), + /// Cannot configure the microvm: {0} + VmSetup(kvm_ioctls::Error), + #[cfg(target_arch = "aarch64")] + /// Failed to save the VM's GIC state: {0} + SaveGic(crate::arch::aarch64::gic::GicError), + #[cfg(target_arch = "aarch64")] + /// Failed to restore the VM's GIC state: {0} + RestoreGic(crate::arch::aarch64::gic::GicError), +} + +/// A wrapper around creating and using a VM. +#[derive(Debug)] +pub struct Vm { + fd: VmFd, + + // Arm specific fields. + // On aarch64 we need to keep around the fd obtained by creating the VGIC device. + #[cfg(target_arch = "aarch64")] + irqchip_handle: Option, +} + +/// Contains Vm functions that are usable across CPU architectures +impl Vm { + /// Create a new `Vm` struct. + pub fn new(kvm: &Kvm) -> Result { + // Create fd for interacting with kvm-vm specific functions. + let vm_fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; + + #[cfg(target_arch = "aarch64")] + { + Ok(Vm { + fd: vm_fd, + irqchip_handle: None, + }) + } + + #[cfg(target_arch = "x86_64")] + { + Ok(Vm { fd: vm_fd }) + } + } + + /// Initializes the guest memory. + pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { + self.set_kvm_memory_regions(guest_mem)?; + #[cfg(target_arch = "x86_64")] + self.fd + .set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) + .map_err(VmError::VmSetup)?; + + Ok(()) + } + + pub(crate) fn set_kvm_memory_regions( + &self, + guest_mem: &GuestMemoryMmap, + ) -> Result<(), VmError> { + guest_mem + .iter() + .zip(0u32..) + .try_for_each(|(region, slot)| { + let flags = if region.bitmap().is_some() { + KVM_MEM_LOG_DIRTY_PAGES + } else { + 0 + }; + + let memory_region = kvm_userspace_memory_region { + slot, + guest_phys_addr: region.start_addr().raw_value(), + memory_size: region.len(), + // It's safe to unwrap because the guest address is valid. + userspace_addr: guest_mem.get_host_address(region.start_addr()).unwrap() as u64, + flags, + }; + + // SAFETY: Safe because the fd is a valid KVM file descriptor. + unsafe { self.fd.set_user_memory_region(memory_region) } + }) + .map_err(VmError::SetUserMemoryRegion)?; + Ok(()) + } + + /// Gets a reference to the kvm file descriptor owned by this VM. + pub fn fd(&self) -> &VmFd { + &self.fd + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use crate::test_utils::single_region_mem; + use crate::vstate::memory::GuestMemoryMmap; + + // Auxiliary function being used throughout the tests. + pub(crate) fn setup_vm() -> (Kvm, Vm) { + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + let vm = Vm::new(&kvm).expect("Cannot create new vm"); + (kvm, vm) + } + + // Auxiliary function being used throughout the tests. + pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm, GuestMemoryMmap) { + let (kvm, vm) = setup_vm(); + let gm = single_region_mem(mem_size); + vm.memory_init(&gm).unwrap(); + (kvm, vm, gm) + } + + #[test] + fn test_new() { + // Testing with a valid /dev/kvm descriptor. + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + Vm::new(&kvm).unwrap(); + } + + #[test] + fn test_vm_memory_init() { + let (_, vm) = setup_vm(); + // Create valid memory region and test that the initialization is successful. + let gm = single_region_mem(0x1000); + vm.memory_init(&gm).unwrap(); + } + + #[test] + fn test_set_kvm_memory_regions() { + let (_, vm) = setup_vm(); + + let gm = single_region_mem(0x1000); + let res = vm.set_kvm_memory_regions(&gm); + res.unwrap(); + + // Trying to set a memory region with a size that is not a multiple of GUEST_PAGE_SIZE + // will result in error. + let gm = single_region_mem(0x10); + let res = vm.set_kvm_memory_regions(&gm); + assert_eq!( + res.unwrap_err().to_string(), + "Cannot set the memory regions: Invalid argument (os error 22)" + ); + } +} diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs new file mode 100644 index 00000000000..95ac742ad76 --- /dev/null +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -0,0 +1,221 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::fmt; + +use kvm_bindings::{ + kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE, + KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, +}; +use serde::{Deserialize, Serialize}; + +use crate::vstate::vm::VmError; +use crate::Vm; + +/// Error type for [`Vm::restore_state`] +#[allow(missing_docs)] +#[cfg(target_arch = "x86_64")] +#[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)] +pub enum RestoreStateError { + /// Set PIT2 error: {0} + SetPit2(kvm_ioctls::Error), + /// Set clock error: {0} + SetClock(kvm_ioctls::Error), + /// Set IrqChipPicMaster error: {0} + SetIrqChipPicMaster(kvm_ioctls::Error), + /// Set IrqChipPicSlave error: {0} + SetIrqChipPicSlave(kvm_ioctls::Error), + /// Set IrqChipIoAPIC error: {0} + SetIrqChipIoAPIC(kvm_ioctls::Error), + /// VM error: {0} + VmError(VmError), +} + +impl Vm { + /// Restores the KVM VM state. + /// + /// # Errors + /// + /// When: + /// - [`kvm_ioctls::VmFd::set_pit`] errors. + /// - [`kvm_ioctls::VmFd::set_clock`] errors. + /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. + /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. + /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. + pub fn restore_state(&mut self, state: &VmState) -> Result<(), RestoreStateError> { + self.fd + .set_pit2(&state.pitstate) + .map_err(RestoreStateError::SetPit2)?; + self.fd + .set_clock(&state.clock) + .map_err(RestoreStateError::SetClock)?; + self.fd + .set_irqchip(&state.pic_master) + .map_err(RestoreStateError::SetIrqChipPicMaster)?; + self.fd + .set_irqchip(&state.pic_slave) + .map_err(RestoreStateError::SetIrqChipPicSlave)?; + self.fd + .set_irqchip(&state.ioapic) + .map_err(RestoreStateError::SetIrqChipIoAPIC)?; + Ok(()) + } + + /// Creates the irq chip and an in-kernel device model for the PIT. + pub fn setup_irqchip(&self) -> Result<(), VmError> { + self.fd.create_irq_chip().map_err(VmError::VmSetup)?; + // We need to enable the emulation of a dummy speaker port stub so that writing to port 0x61 + // (i.e. KVM_SPEAKER_BASE_ADDRESS) does not trigger an exit to user space. + let pit_config = kvm_pit_config { + flags: KVM_PIT_SPEAKER_DUMMY, + ..Default::default() + }; + self.fd.create_pit2(pit_config).map_err(VmError::VmSetup) + } + + /// Saves and returns the Kvm Vm state. + pub fn save_state(&self) -> Result { + let pitstate = self.fd.get_pit2().map_err(VmError::VmGetPit2)?; + + let mut clock = self.fd.get_clock().map_err(VmError::VmGetClock)?; + // This bit is not accepted in SET_CLOCK, clear it. + clock.flags &= !KVM_CLOCK_TSC_STABLE; + + let mut pic_master = kvm_irqchip { + chip_id: KVM_IRQCHIP_PIC_MASTER, + ..Default::default() + }; + self.fd + .get_irqchip(&mut pic_master) + .map_err(VmError::VmGetIrqChip)?; + + let mut pic_slave = kvm_irqchip { + chip_id: KVM_IRQCHIP_PIC_SLAVE, + ..Default::default() + }; + self.fd + .get_irqchip(&mut pic_slave) + .map_err(VmError::VmGetIrqChip)?; + + let mut ioapic = kvm_irqchip { + chip_id: KVM_IRQCHIP_IOAPIC, + ..Default::default() + }; + self.fd + .get_irqchip(&mut ioapic) + .map_err(VmError::VmGetIrqChip)?; + + Ok(VmState { + pitstate, + clock, + pic_master, + pic_slave, + ioapic, + }) + } +} + +#[derive(Default, Deserialize, Serialize)] +/// Structure holding VM kvm state. +pub struct VmState { + pitstate: kvm_pit_state2, + clock: kvm_clock_data, + // TODO: rename this field to adopt inclusive language once Linux updates it, too. + pic_master: kvm_irqchip, + // TODO: rename this field to adopt inclusive language once Linux updates it, too. + pic_slave: kvm_irqchip, + ioapic: kvm_irqchip, +} + +impl fmt::Debug for VmState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("VmState") + .field("pitstate", &self.pitstate) + .field("clock", &self.clock) + .field("pic_master", &"?") + .field("pic_slave", &"?") + .field("ioapic", &"?") + .finish() + } +} + +#[cfg(test)] +mod tests { + use kvm_bindings::{ + KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, + KVM_PIT_SPEAKER_DUMMY, + }; + + use crate::snapshot::Snapshot; + use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; + use crate::vstate::vm::VmState; + + #[cfg(target_arch = "x86_64")] + #[test] + fn test_vm_save_restore_state() { + let (_, vm) = setup_vm(); + // Irqchips, clock and pitstate are not configured so trying to save state should fail. + vm.save_state().unwrap_err(); + + let (_, vm, _mem) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); + + let vm_state = vm.save_state().unwrap(); + assert_eq!( + vm_state.pitstate.flags | KVM_PIT_SPEAKER_DUMMY, + KVM_PIT_SPEAKER_DUMMY + ); + assert_eq!(vm_state.clock.flags & KVM_CLOCK_TSC_STABLE, 0); + assert_eq!(vm_state.pic_master.chip_id, KVM_IRQCHIP_PIC_MASTER); + assert_eq!(vm_state.pic_slave.chip_id, KVM_IRQCHIP_PIC_SLAVE); + assert_eq!(vm_state.ioapic.chip_id, KVM_IRQCHIP_IOAPIC); + + let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); + + vm.restore_state(&vm_state).unwrap(); + } + + #[cfg(target_arch = "x86_64")] + #[test] + fn test_vm_save_restore_state_bad_irqchip() { + use kvm_bindings::KVM_NR_IRQCHIPS; + + let (_, vm, _mem) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); + let mut vm_state = vm.save_state().unwrap(); + + let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); + + // Try to restore an invalid PIC Master chip ID + let orig_master_chip_id = vm_state.pic_master.chip_id; + vm_state.pic_master.chip_id = KVM_NR_IRQCHIPS; + vm.restore_state(&vm_state).unwrap_err(); + vm_state.pic_master.chip_id = orig_master_chip_id; + + // Try to restore an invalid PIC Slave chip ID + let orig_slave_chip_id = vm_state.pic_slave.chip_id; + vm_state.pic_slave.chip_id = KVM_NR_IRQCHIPS; + vm.restore_state(&vm_state).unwrap_err(); + vm_state.pic_slave.chip_id = orig_slave_chip_id; + + // Try to restore an invalid IOPIC chip ID + vm_state.ioapic.chip_id = KVM_NR_IRQCHIPS; + vm.restore_state(&vm_state).unwrap_err(); + } + + #[cfg(target_arch = "x86_64")] + #[test] + fn test_vmstate_serde() { + let mut snapshot_data = vec![0u8; 10000]; + + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); + let state = vm.save_state().unwrap(); + Snapshot::serialize(&mut snapshot_data.as_mut_slice(), &state).unwrap(); + let restored_state: VmState = Snapshot::deserialize(&mut snapshot_data.as_slice()).unwrap(); + + vm.restore_state(&restored_state).unwrap(); + } +} From 5eaf2ebe2dd57f2938cc594bc55fc18c88bd06e2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 12:42:19 +0000 Subject: [PATCH 229/464] refactor: Split `VmError` enum into arch specific versions Introduce `enum ArchVmError` which contains architecture specific variants for VM operations (mostly related to snapshot creation/restore). Do this by adapting exiting architecture specific enums that were used for snapshot restoration (x86_64)/GIC creation (aarch64). While we're at it, remove unused/duplicated enum variants, and on x86 use the SetIrqChip enum variant for failures inside `setup_irq_chip` instead of producing some generic `VmError`. Admittedly, there's a lot more cleanup that can be done here, but for now this is enough to attain my goals (separating architecture specific code). No functional change intended (apart from error messages changing). Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 6 ++-- src/vmm/src/persist.rs | 2 +- src/vmm/src/vstate/vm/aarch64.rs | 33 +++++++++----------- src/vmm/src/vstate/vm/mod.rs | 31 ++----------------- src/vmm/src/vstate/vm/x86_64.rs | 53 ++++++++++++++++++++------------ 5 files changed, 56 insertions(+), 69 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 27de9f6afa6..0db73698490 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -71,7 +71,7 @@ use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; -use crate::vstate::vm::Vm; +use crate::vstate::vm::{Vm, VmError}; use crate::{device_manager, EventManager, Vmm, VmmError}; /// Errors associated with starting the instance. @@ -436,7 +436,7 @@ pub enum BuildMicrovmFromSnapshotError { /// Could not set TSC scaling within the snapshot: {0} SetTsc(#[from] crate::vstate::vcpu::SetTscError), /// Failed to restore microVM state: {0} - RestoreState(#[from] crate::vstate::vm::RestoreStateError), + RestoreState(#[from] crate::vstate::vm::ArchVmError), /// Failed to update microVM configuration: {0} VmUpdateConfig(#[from] MachineConfigError), /// Failed to restore MMIO device: {0} @@ -675,6 +675,7 @@ where #[cfg(target_arch = "x86_64")] pub fn setup_interrupt_controller(vm: &mut Vm) -> Result<(), StartMicrovmError> { vm.setup_irqchip() + .map_err(VmError::Arch) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal) } @@ -683,6 +684,7 @@ pub fn setup_interrupt_controller(vm: &mut Vm) -> Result<(), StartMicrovmError> #[cfg(target_arch = "aarch64")] pub fn setup_interrupt_controller(vm: &mut Vm, vcpu_count: u8) -> Result<(), StartMicrovmError> { vm.setup_irqchip(vcpu_count) + .map_err(VmError::Arch) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal) } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 3c5f3e7e754..05529107b6b 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -129,7 +129,7 @@ pub enum MicrovmStateError { /// Cannot save Vcpu state: {0} SaveVcpuState(vstate::vcpu::VcpuError), /// Cannot save Vm state: {0} - SaveVmState(vstate::vm::VmError), + SaveVmState(vstate::vm::ArchVmError), /// Cannot signal Vcpu: {0} SignalVcpu(VcpuSendEventError), /// Vcpu is in unexpected state. diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 0925ad4d7e2..45d9da0dc10 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -4,24 +4,25 @@ use serde::{Deserialize, Serialize}; use crate::arch::aarch64::gic::GicState; -use crate::vstate::vm::VmError; use crate::Vm; /// Error type for [`Vm::restore_state`] -#[derive(Debug, thiserror::Error, displaydoc::Display)] -pub enum RestoreStateError { - /// {0} - GicError(crate::arch::aarch64::gic::GicError), - /// {0} - VmError(VmError), +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum ArchVmError { + /// Error creating the global interrupt controller: {0} + VmCreateGIC(crate::arch::aarch64::gic::GicError), + /// Failed to save the VM's GIC state: {0} + SaveGic(crate::arch::aarch64::gic::GicError), + /// Failed to restore the VM's GIC state: {0} + RestoreGic(crate::arch::aarch64::gic::GicError), } impl Vm { /// Creates the GIC (Global Interrupt Controller). - pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), VmError> { + pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), ArchVmError> { self.irqchip_handle = Some( crate::arch::aarch64::gic::create_gic(&self.fd, vcpu_count.into(), None) - .map_err(VmError::VmCreateGIC)?, + .map_err(ArchVmError::VmCreateGIC)?, ); Ok(()) } @@ -32,12 +33,12 @@ impl Vm { } /// Saves and returns the Kvm Vm state. - pub fn save_state(&self, mpidrs: &[u64]) -> Result { - Ok(crate::vstate::vm::VmState { + pub fn save_state(&self, mpidrs: &[u64]) -> Result { + Ok(VmState { gic: self .get_irqchip() .save_device(mpidrs) - .map_err(VmError::SaveGic)?, + .map_err(ArchVmError::SaveGic)?, }) } @@ -46,14 +47,10 @@ impl Vm { /// # Errors /// /// When [`crate::arch::aarch64::gic::GICDevice::restore_device`] errors. - pub fn restore_state( - &mut self, - mpidrs: &[u64], - state: &crate::vstate::vm::VmState, - ) -> Result<(), RestoreStateError> { + pub fn restore_state(&mut self, mpidrs: &[u64], state: &VmState) -> Result<(), ArchVmError> { self.get_irqchip() .restore_device(mpidrs, &state.gic) - .map_err(RestoreStateError::GicError)?; + .map_err(ArchVmError::RestoreGic)?; Ok(()) } } diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 65c3ab43f74..5c54643d258 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -22,7 +22,7 @@ mod arch; #[path = "aarch64.rs"] mod arch; -pub use arch::{RestoreStateError, VmState}; +pub use arch::{ArchVmError, VmState}; /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work @@ -31,37 +31,12 @@ pub use arch::{RestoreStateError, VmState}; pub enum VmError { /// Cannot set the memory regions: {0} SetUserMemoryRegion(kvm_ioctls::Error), - #[cfg(target_arch = "aarch64")] - /// Error creating the global interrupt controller: {0} - VmCreateGIC(crate::arch::aarch64::gic::GicError), /// Cannot open the VM file descriptor: {0} VmFd(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm pit state: {0} - VmGetPit2(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm clock: {0} - VmGetClock(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get KVM vm irqchip: {0} - VmGetIrqChip(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm pit state: {0} - VmSetPit2(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm clock: {0} - VmSetClock(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to set KVM vm irqchip: {0} - VmSetIrqChip(kvm_ioctls::Error), /// Cannot configure the microvm: {0} VmSetup(kvm_ioctls::Error), - #[cfg(target_arch = "aarch64")] - /// Failed to save the VM's GIC state: {0} - SaveGic(crate::arch::aarch64::gic::GicError), - #[cfg(target_arch = "aarch64")] - /// Failed to restore the VM's GIC state: {0} - RestoreGic(crate::arch::aarch64::gic::GicError), + /// {0} + Arch(#[from] ArchVmError), } /// A wrapper around creating and using a VM. diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 95ac742ad76..9b38e304e9a 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -9,14 +9,13 @@ use kvm_bindings::{ }; use serde::{Deserialize, Serialize}; -use crate::vstate::vm::VmError; use crate::Vm; /// Error type for [`Vm::restore_state`] #[allow(missing_docs)] #[cfg(target_arch = "x86_64")] -#[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)] -pub enum RestoreStateError { +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum ArchVmError { /// Set PIT2 error: {0} SetPit2(kvm_ioctls::Error), /// Set clock error: {0} @@ -27,8 +26,18 @@ pub enum RestoreStateError { SetIrqChipPicSlave(kvm_ioctls::Error), /// Set IrqChipIoAPIC error: {0} SetIrqChipIoAPIC(kvm_ioctls::Error), - /// VM error: {0} - VmError(VmError), + /// Failed to get KVM vm pit state: {0} + VmGetPit2(kvm_ioctls::Error), + /// Failed to get KVM vm clock: {0} + VmGetClock(kvm_ioctls::Error), + /// Failed to get KVM vm irqchip: {0} + VmGetIrqChip(kvm_ioctls::Error), + /// Failed to set KVM vm pit state: {0} + VmSetPit2(kvm_ioctls::Error), + /// Failed to set KVM vm clock: {0} + VmSetClock(kvm_ioctls::Error), + /// Failed to set KVM vm irqchip: {0} + VmSetIrqChip(kvm_ioctls::Error), } impl Vm { @@ -42,42 +51,46 @@ impl Vm { /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. - pub fn restore_state(&mut self, state: &VmState) -> Result<(), RestoreStateError> { + pub fn restore_state(&mut self, state: &VmState) -> Result<(), ArchVmError> { self.fd .set_pit2(&state.pitstate) - .map_err(RestoreStateError::SetPit2)?; + .map_err(ArchVmError::SetPit2)?; self.fd .set_clock(&state.clock) - .map_err(RestoreStateError::SetClock)?; + .map_err(ArchVmError::SetClock)?; self.fd .set_irqchip(&state.pic_master) - .map_err(RestoreStateError::SetIrqChipPicMaster)?; + .map_err(ArchVmError::SetIrqChipPicMaster)?; self.fd .set_irqchip(&state.pic_slave) - .map_err(RestoreStateError::SetIrqChipPicSlave)?; + .map_err(ArchVmError::SetIrqChipPicSlave)?; self.fd .set_irqchip(&state.ioapic) - .map_err(RestoreStateError::SetIrqChipIoAPIC)?; + .map_err(ArchVmError::SetIrqChipIoAPIC)?; Ok(()) } /// Creates the irq chip and an in-kernel device model for the PIT. - pub fn setup_irqchip(&self) -> Result<(), VmError> { - self.fd.create_irq_chip().map_err(VmError::VmSetup)?; + pub fn setup_irqchip(&self) -> Result<(), ArchVmError> { + self.fd + .create_irq_chip() + .map_err(ArchVmError::VmSetIrqChip)?; // We need to enable the emulation of a dummy speaker port stub so that writing to port 0x61 // (i.e. KVM_SPEAKER_BASE_ADDRESS) does not trigger an exit to user space. let pit_config = kvm_pit_config { flags: KVM_PIT_SPEAKER_DUMMY, ..Default::default() }; - self.fd.create_pit2(pit_config).map_err(VmError::VmSetup) + self.fd + .create_pit2(pit_config) + .map_err(ArchVmError::VmSetIrqChip) } /// Saves and returns the Kvm Vm state. - pub fn save_state(&self) -> Result { - let pitstate = self.fd.get_pit2().map_err(VmError::VmGetPit2)?; + pub fn save_state(&self) -> Result { + let pitstate = self.fd.get_pit2().map_err(ArchVmError::VmGetPit2)?; - let mut clock = self.fd.get_clock().map_err(VmError::VmGetClock)?; + let mut clock = self.fd.get_clock().map_err(ArchVmError::VmGetClock)?; // This bit is not accepted in SET_CLOCK, clear it. clock.flags &= !KVM_CLOCK_TSC_STABLE; @@ -87,7 +100,7 @@ impl Vm { }; self.fd .get_irqchip(&mut pic_master) - .map_err(VmError::VmGetIrqChip)?; + .map_err(ArchVmError::VmGetIrqChip)?; let mut pic_slave = kvm_irqchip { chip_id: KVM_IRQCHIP_PIC_SLAVE, @@ -95,7 +108,7 @@ impl Vm { }; self.fd .get_irqchip(&mut pic_slave) - .map_err(VmError::VmGetIrqChip)?; + .map_err(ArchVmError::VmGetIrqChip)?; let mut ioapic = kvm_irqchip { chip_id: KVM_IRQCHIP_IOAPIC, @@ -103,7 +116,7 @@ impl Vm { }; self.fd .get_irqchip(&mut ioapic) - .map_err(VmError::VmGetIrqChip)?; + .map_err(ArchVmError::VmGetIrqChip)?; Ok(VmState { pitstate, From de011a0ad163ed1e536bba09673fabad806c6991 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 13:03:42 +0000 Subject: [PATCH 230/464] refactor: Split `struct Vm` into arch-specific structs Similarly to what we do in the vcpu module for the Vcpu/KvmVcpu structs. The difference is that we do not implement any function on `ArchVm`, so that common fields like `fd` can live in `Vm`, instead of needing to be duplicated into all the `ArchVm` types. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vm/aarch64.rs | 23 ++++++++++++++++++-- src/vmm/src/vstate/vm/mod.rs | 36 ++------------------------------ src/vmm/src/vstate/vm/x86_64.rs | 17 +++++++++++++-- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 45d9da0dc10..9ff48c6c7ee 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -1,10 +1,20 @@ // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; +use super::VmError; use crate::arch::aarch64::gic::GicState; -use crate::Vm; +use crate::vstate::kvm::Kvm; + +/// Structure representing the current architecture's understand of what a "virtual machine" is. +#[derive(Debug)] +pub struct ArchVm { + pub(super) fd: VmFd, + // On aarch64 we need to keep around the fd obtained by creating the VGIC device. + irqchip_handle: Option, +} /// Error type for [`Vm::restore_state`] #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] @@ -17,7 +27,16 @@ pub enum ArchVmError { RestoreGic(crate::arch::aarch64::gic::GicError), } -impl Vm { +impl ArchVm { + /// Create a new `Vm` struct. + pub fn new(kvm: &Kvm) -> Result { + let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; + Ok(ArchVm { + fd, + irqchip_handle: None, + }) + } + /// Creates the GIC (Global Interrupt Controller). pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), ArchVmError> { self.irqchip_handle = Some( diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 5c54643d258..df4e72c2e95 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -8,11 +8,8 @@ use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; use kvm_ioctls::VmFd; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::gic::GICDevice; #[cfg(target_arch = "x86_64")] use crate::utils::u64_to_usize; -use crate::vstate::kvm::Kvm; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; #[cfg(target_arch = "x86_64")] @@ -22,7 +19,7 @@ mod arch; #[path = "aarch64.rs"] mod arch; -pub use arch::{ArchVmError, VmState}; +pub use arch::{ArchVm as Vm, ArchVmError, VmState}; /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work @@ -39,38 +36,8 @@ pub enum VmError { Arch(#[from] ArchVmError), } -/// A wrapper around creating and using a VM. -#[derive(Debug)] -pub struct Vm { - fd: VmFd, - - // Arm specific fields. - // On aarch64 we need to keep around the fd obtained by creating the VGIC device. - #[cfg(target_arch = "aarch64")] - irqchip_handle: Option, -} - /// Contains Vm functions that are usable across CPU architectures impl Vm { - /// Create a new `Vm` struct. - pub fn new(kvm: &Kvm) -> Result { - // Create fd for interacting with kvm-vm specific functions. - let vm_fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; - - #[cfg(target_arch = "aarch64")] - { - Ok(Vm { - fd: vm_fd, - irqchip_handle: None, - }) - } - - #[cfg(target_arch = "x86_64")] - { - Ok(Vm { fd: vm_fd }) - } - } - /// Initializes the guest memory. pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { self.set_kvm_memory_regions(guest_mem)?; @@ -122,6 +89,7 @@ impl Vm { pub(crate) mod tests { use super::*; use crate::test_utils::single_region_mem; + use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; // Auxiliary function being used throughout the tests. diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 9b38e304e9a..1e4bef11ce5 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -7,9 +7,10 @@ use kvm_bindings::{ kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, }; +use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; -use crate::Vm; +use crate::vstate::vm::VmError; /// Error type for [`Vm::restore_state`] #[allow(missing_docs)] @@ -40,7 +41,19 @@ pub enum ArchVmError { VmSetIrqChip(kvm_ioctls::Error), } -impl Vm { +/// Structure representing the current architecture's understand of what a "virtual machine" is. +#[derive(Debug)] +pub struct ArchVm { + pub(super) fd: VmFd, +} + +impl ArchVm { + /// Create a new `Vm` struct. + pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { + let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; + Ok(ArchVm { fd }) + } + /// Restores the KVM VM state. /// /// # Errors From add1d52c103cc21608d593ff66b0406f35d3c01f Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 13:19:50 +0000 Subject: [PATCH 231/464] refactor: Store msrs_to_save in `struct Vm` instead of `Kvm` This allows us to not need to feed `struct Kvm` all the way down to Vcpu creation. While we're at it, abstract away the `MsrList` type, and just have a helper that returns a slice of u32 (as every call site converts the MsrList to this anyway). Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 17 ++++++---------- src/vmm/src/vstate/kvm.rs | 15 ++++++-------- src/vmm/src/vstate/vcpu/aarch64.rs | 32 +++++++++++++++--------------- src/vmm/src/vstate/vcpu/mod.rs | 11 +++++----- src/vmm/src/vstate/vcpu/x86_64.rs | 15 +++++++------- src/vmm/src/vstate/vm/aarch64.rs | 2 +- src/vmm/src/vstate/vm/x86_64.rs | 14 +++++++++++-- 7 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 0db73698490..1a15dbce2f7 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -192,7 +192,7 @@ fn create_vmm_and_vcpus( #[cfg(target_arch = "x86_64")] let (vcpus, pio_device_manager) = { setup_interrupt_controller(&mut vm)?; - let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; + let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; // Make stdout non blocking. set_stdout_nonblocking(); @@ -224,7 +224,7 @@ fn create_vmm_and_vcpus( // Search for `kvm_arch_vcpu_create` in arch/arm/kvm/arm.c. #[cfg(target_arch = "aarch64")] let vcpus = { - let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; + let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; setup_interrupt_controller(&mut vm, vcpu_count)?; vcpus }; @@ -746,16 +746,11 @@ fn attach_legacy_devices_aarch64( .map_err(VmmError::RegisterMMIODevice) } -fn create_vcpus( - kvm: &Kvm, - vm: &Vm, - vcpu_count: u8, - exit_evt: &EventFd, -) -> Result, VmmError> { +fn create_vcpus(vm: &Vm, vcpu_count: u8, exit_evt: &EventFd) -> Result, VmmError> { let mut vcpus = Vec::with_capacity(vcpu_count as usize); for cpu_idx in 0..vcpu_count { let exit_evt = exit_evt.try_clone().map_err(VmmError::EventFd)?; - let vcpu = Vcpu::new(cpu_idx, vm, kvm, exit_evt).map_err(VmmError::VcpuCreate)?; + let vcpu = Vcpu::new(cpu_idx, vm, exit_evt).map_err(VmmError::VcpuCreate)?; vcpus.push(vcpu); } Ok(vcpus) @@ -1164,7 +1159,7 @@ pub(crate) mod tests { #[cfg(target_arch = "aarch64")] { let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); - let _vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap(); + let _vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); setup_interrupt_controller(&mut vm, 1).unwrap(); } @@ -1399,7 +1394,7 @@ pub(crate) mod tests { #[cfg(target_arch = "x86_64")] setup_interrupt_controller(&mut vm).unwrap(); - let vcpu_vec = create_vcpus(&kvm, &vm, vcpu_count, &evfd).unwrap(); + let vcpu_vec = create_vcpus(&vm, vcpu_count, &evfd).unwrap(); assert_eq!(vcpu_vec.len(), vcpu_count as usize); } diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index 59b192dbe09..20585b337fc 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -23,9 +23,6 @@ pub enum KvmError { configured on the /dev/kvm file's ACL. */ Kvm(kvm_ioctls::Error), #[cfg(target_arch = "x86_64")] - /// Failed to get MSR index list to save into snapshots: {0} - GetMsrsToSave(crate::arch::x86_64::msr::MsrError), - #[cfg(target_arch = "x86_64")] /// Failed to get supported cpuid: {0} GetSupportedCpuId(kvm_ioctls::Error), /// The number of configured slots is bigger than the maximum reported by KVM @@ -45,9 +42,6 @@ pub struct Kvm { #[cfg(target_arch = "x86_64")] /// Supported CpuIds. pub supported_cpuid: CpuId, - #[cfg(target_arch = "x86_64")] - /// Msrs needed to be saved on snapshot creation. - pub msrs_to_save: MsrList, } impl Kvm { @@ -82,19 +76,22 @@ impl Kvm { let supported_cpuid = kvm_fd .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) .map_err(KvmError::GetSupportedCpuId)?; - let msrs_to_save = crate::arch::x86_64::msr::get_msrs_to_save(&kvm_fd) - .map_err(KvmError::GetMsrsToSave)?; Ok(Kvm { fd: kvm_fd, max_memslots, kvm_cap_modifiers, supported_cpuid, - msrs_to_save, }) } } + /// Msrs needed to be saved on snapshot creation. + #[cfg(target_arch = "x86_64")] + pub fn msrs_to_save(&self) -> Result { + crate::arch::x86_64::msr::get_msrs_to_save(&self.fd) + } + /// Check guest memory does not have more regions than kvm allows. pub fn check_memory(&self, guest_mem: &GuestMemoryMmap) -> Result<(), KvmError> { if guest_mem.num_regions() > self.max_memslots { diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 9db1173eeb8..7bdde9b9d1f 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -22,7 +22,7 @@ use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; use crate::cpu_config::templates::CpuConfiguration; use crate::logger::{error, IncMetric, METRICS}; use crate::vcpu::{VcpuConfig, VcpuError}; -use crate::vstate::kvm::{Kvm, OptionalCapabilities}; +use crate::vstate::kvm::OptionalCapabilities; use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuEmulation; use crate::vstate::vm::Vm; @@ -78,7 +78,7 @@ impl KvmVcpu { /// /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. - pub fn new(index: u8, vm: &Vm, _: &Kvm) -> Result { + pub fn new(index: u8, vm: &Vm) -> Result { let kvm_vcpu = vm .fd() .create_vcpu(index.into()) @@ -315,7 +315,7 @@ mod tests { fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); - let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); @@ -324,11 +324,11 @@ mod tests { #[test] fn test_create_vcpu() { - let (kvm, vm, _) = setup_vm_with_memory(0x1000); + let (_, vm, _) = setup_vm_with_memory(0x1000); unsafe { libc::close(vm.fd().as_raw_fd()) }; - let err = KvmVcpu::new(0, &vm, &kvm); + let err = KvmVcpu::new(0, &vm); assert_eq!( err.err().unwrap().to_string(), "Error creating vcpu: Bad file descriptor (os error 9)".to_string() @@ -378,8 +378,8 @@ mod tests { #[test] fn test_init_vcpu() { - let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); // KVM_ARM_VCPU_PSCI_0_2 is set by default. @@ -397,8 +397,8 @@ mod tests { #[test] fn test_vcpu_save_restore_state() { - let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); // Calling KVM_GET_REGLIST before KVM_VCPU_INIT will result in error. @@ -441,8 +441,8 @@ mod tests { // // This should fail with ENOEXEC. // https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165 - let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); - let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu.dump_cpu_config().unwrap_err(); @@ -451,8 +451,8 @@ mod tests { #[test] fn test_dump_cpu_config_after_init() { // Test `dump_cpu_config()` after `KVM_VCPU_INIT`. - let (kvm, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu.init(&[]).unwrap(); @@ -461,10 +461,10 @@ mod tests { #[test] fn test_setup_non_boot_vcpu() { - let (kvm, vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu1 = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap(); vcpu1.init(&[]).unwrap(); - let mut vcpu2 = KvmVcpu::new(1, &vm, &kvm).unwrap(); + let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap(); vcpu2.init(&[]).unwrap(); } diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index d9aa0abd1a8..363964b6edc 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -44,8 +44,6 @@ pub use aarch64::{KvmVcpuError, *}; #[cfg(target_arch = "x86_64")] pub use x86_64::{KvmVcpuError, *}; -use super::kvm::Kvm; - /// Signal number (SIGRTMIN) used to kick Vcpus. pub const VCPU_RTSIG_OFFSET: i32 = 0; @@ -214,10 +212,10 @@ impl Vcpu { /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. /// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits. - pub fn new(index: u8, vm: &Vm, kvm: &Kvm, exit_evt: EventFd) -> Result { + pub fn new(index: u8, vm: &Vm, exit_evt: EventFd) -> Result { let (event_sender, event_receiver) = channel(); let (response_sender, response_receiver) = channel(); - let kvm_vcpu = KvmVcpu::new(index, vm, kvm).unwrap(); + let kvm_vcpu = KvmVcpu::new(index, vm).unwrap(); Ok(Vcpu { exit_evt, @@ -787,6 +785,7 @@ pub(crate) mod tests { use crate::devices::BusDevice; use crate::seccomp::get_empty_filters; use crate::utils::signal::validate_signal_num; + use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuError as EmulationError; use crate::vstate::vm::tests::setup_vm_with_memory; @@ -937,7 +936,7 @@ pub(crate) mod tests { #[cfg(target_arch = "aarch64")] let vcpu = { - let mut vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap(); + let mut vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); vcpu.kvm_vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu @@ -945,7 +944,7 @@ pub(crate) mod tests { #[cfg(target_arch = "x86_64")] let vcpu = { vm.setup_irqchip().unwrap(); - Vcpu::new(1, &vm, &kvm, exit_evt).unwrap() + Vcpu::new(1, &vm, exit_evt).unwrap() }; (kvm, vm, vcpu, gm) } diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 39ff0879ee8..85c2db3868f 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -23,7 +23,6 @@ use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError}; use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError}; use crate::cpu_config::x86_64::{cpuid, CpuConfiguration}; use crate::logger::{IncMetric, METRICS}; -use crate::vstate::kvm::Kvm; use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation}; use crate::vstate::vm::Vm; @@ -165,7 +164,7 @@ impl KvmVcpu { /// /// * `index` - Represents the 0-based CPU index between [0, max vcpus). /// * `vm` - The vm to which this vcpu will get attached. - pub fn new(index: u8, vm: &Vm, kvm: &Kvm) -> Result { + pub fn new(index: u8, vm: &Vm) -> Result { let kvm_vcpu = vm .fd() .create_vcpu(index.into()) @@ -175,7 +174,7 @@ impl KvmVcpu { index, fd: kvm_vcpu, peripherals: Default::default(), - msrs_to_save: kvm.msrs_to_save.as_slice().to_vec(), + msrs_to_save: vm.msrs_to_save().to_vec(), }) } @@ -726,6 +725,7 @@ mod tests { StaticCpuTemplate, }; use crate::cpu_config::x86_64::cpuid::{Cpuid, CpuidEntry, CpuidKey}; + use crate::vstate::kvm::Kvm; use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; use crate::vstate::vm::Vm; @@ -750,7 +750,7 @@ mod tests { fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size); vm.setup_irqchip().unwrap(); - let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let vcpu = KvmVcpu::new(0, &vm).unwrap(); (kvm, vm, vcpu, vm_mem) } @@ -1168,11 +1168,11 @@ mod tests { #[test] fn test_get_msr_chunks_preserved_order() { // Regression test for #4666 - let (kvm, vm) = setup_vm(); - let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap(); + let (_, vm) = setup_vm(); + let vcpu = KvmVcpu::new(0, &vm).unwrap(); // The list of supported MSR indices, in the order they were returned by KVM - let msrs_to_save = kvm.msrs_to_save; + let msrs_to_save = vm.msrs_to_save(); // The MSRs after processing. The order should be identical to the one returned by KVM, with // the exception of deferred MSRs, which should be moved to the end (but show up in the same // order as they are listed in [`DEFERRED_MSRS`]. @@ -1185,7 +1185,6 @@ mod tests { .flat_map(|chunk| chunk.as_slice().iter()) .zip( msrs_to_save - .as_slice() .iter() .filter(|&idx| !DEFERRED_MSRS.contains(idx)) .chain(DEFERRED_MSRS.iter()), diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 9ff48c6c7ee..593ae7bc5ea 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use super::VmError; use crate::arch::aarch64::gic::GicState; -use crate::vstate::kvm::Kvm; +use crate::Kvm; /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 1e4bef11ce5..19af125e5ec 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -4,12 +4,13 @@ use std::fmt; use kvm_bindings::{ - kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE, + kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, MsrList, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, }; use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; +use crate::arch::x86_64::msr::MsrError; use crate::vstate::vm::VmError; /// Error type for [`Vm::restore_state`] @@ -39,19 +40,23 @@ pub enum ArchVmError { VmSetClock(kvm_ioctls::Error), /// Failed to set KVM vm irqchip: {0} VmSetIrqChip(kvm_ioctls::Error), + /// Failed to get MSR index list to save into snapshots: {0} + GetMsrsToSave(MsrError), } /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] pub struct ArchVm { pub(super) fd: VmFd, + msrs_to_save: MsrList, } impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; - Ok(ArchVm { fd }) + let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; + Ok(ArchVm { fd, msrs_to_save }) } /// Restores the KVM VM state. @@ -139,6 +144,11 @@ impl ArchVm { ioapic, }) } + + /// Gets the list of MSRs to save when creating snapshots + pub fn msrs_to_save(&self) -> &[u32] { + self.msrs_to_save.as_slice() + } } #[derive(Default, Deserialize, Serialize)] From 9aa835738b7a76836acfba2ea8a28511d3567cd0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 13:55:46 +0000 Subject: [PATCH 232/464] refactor: move vcpu creation into `struct Vm` This abstracts away the weird irqchip setup dance that builder.rs has been doing (where depending on architecture, irqchip needs to be created before or after vcpu creation. Removes a whole bunch of code that builder.rs that didn't really have too much business being there Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 102 ++++----------------------- src/vmm/src/device_manager/legacy.rs | 4 +- src/vmm/src/device_manager/mmio.rs | 14 ++-- src/vmm/src/vstate/vm/aarch64.rs | 12 ++++ src/vmm/src/vstate/vm/mod.rs | 47 +++++++++++- src/vmm/src/vstate/vm/x86_64.rs | 9 +++ 6 files changed, 87 insertions(+), 101 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 1a15dbce2f7..b450ce50b10 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -71,7 +71,7 @@ use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; -use crate::vstate::vm::{Vm, VmError}; +use crate::vstate::vm::Vm; use crate::{device_manager, EventManager, Vmm, VmmError}; /// Errors associated with starting the instance. @@ -175,10 +175,6 @@ fn create_vmm_and_vcpus( .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; - let vcpus_exit_evt = EventFd::new(libc::EFD_NONBLOCK) - .map_err(VmmError::EventFd) - .map_err(Internal)?; - let resource_allocator = ResourceAllocator::new()?; // Instantiate the MMIO device manager. @@ -187,13 +183,13 @@ fn create_vmm_and_vcpus( // Instantiate ACPI device manager. let acpi_device_manager = ACPIDeviceManager::new(); - // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS` - // while on aarch64 we need to do it the other way around. - #[cfg(target_arch = "x86_64")] - let (vcpus, pio_device_manager) = { - setup_interrupt_controller(&mut vm)?; - let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; + let (vcpus, vcpus_exit_evt) = vm + .create_vcpus(vcpu_count) + .map_err(VmmError::Vm) + .map_err(Internal)?; + #[cfg(target_arch = "x86_64")] + let pio_device_manager = { // Make stdout non blocking. set_stdout_nonblocking(); @@ -208,25 +204,10 @@ fn create_vmm_and_vcpus( .map_err(Internal)?; // create pio dev manager with legacy devices - let pio_device_manager = { - // TODO Remove these unwraps. - let mut pio_dev_mgr = PortIODeviceManager::new(serial_device, reset_evt).unwrap(); - pio_dev_mgr.register_devices(vm.fd()).unwrap(); - pio_dev_mgr - }; - - (vcpus, pio_device_manager) - }; - - // On aarch64, the vCPUs need to be created (i.e call KVM_CREATE_VCPU) before setting up the - // IRQ chip because the `KVM_CREATE_VCPU` ioctl will return error if the IRQCHIP - // was already initialized. - // Search for `kvm_arch_vcpu_create` in arch/arm/kvm/arm.c. - #[cfg(target_arch = "aarch64")] - let vcpus = { - let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?; - setup_interrupt_controller(&mut vm, vcpu_count)?; - vcpus + // TODO Remove these unwraps. + let mut pio_dev_mgr = PortIODeviceManager::new(serial_device, reset_evt).unwrap(); + pio_dev_mgr.register_devices(vm.fd()).unwrap(); + pio_dev_mgr }; let vmm = Vmm { @@ -671,24 +652,6 @@ where }) } -/// Sets up the irqchip for a x86_64 microVM. -#[cfg(target_arch = "x86_64")] -pub fn setup_interrupt_controller(vm: &mut Vm) -> Result<(), StartMicrovmError> { - vm.setup_irqchip() - .map_err(VmError::Arch) - .map_err(VmmError::Vm) - .map_err(StartMicrovmError::Internal) -} - -/// Sets up the irqchip for a aarch64 microVM. -#[cfg(target_arch = "aarch64")] -pub fn setup_interrupt_controller(vm: &mut Vm, vcpu_count: u8) -> Result<(), StartMicrovmError> { - vm.setup_irqchip(vcpu_count) - .map_err(VmError::Arch) - .map_err(VmmError::Vm) - .map_err(StartMicrovmError::Internal) -} - /// Sets up the serial device. pub fn setup_serial_device( event_manager: &mut EventManager, @@ -746,16 +709,6 @@ fn attach_legacy_devices_aarch64( .map_err(VmmError::RegisterMMIODevice) } -fn create_vcpus(vm: &Vm, vcpu_count: u8, exit_evt: &EventFd) -> Result, VmmError> { - let mut vcpus = Vec::with_capacity(vcpu_count as usize); - for cpu_idx in 0..vcpu_count { - let exit_evt = exit_evt.try_clone().map_err(VmmError::EventFd)?; - let vcpu = Vcpu::new(cpu_idx, vm, exit_evt).map_err(VmmError::VcpuCreate)?; - vcpus.push(vcpu); - } - Ok(vcpus) -} - /// Configures the system for booting Linux. #[cfg_attr(target_arch = "aarch64", allow(unused))] pub fn configure_system_for_boot( @@ -1127,11 +1080,6 @@ pub(crate) mod tests { pub(crate) fn default_vmm() -> Vmm { let guest_memory = arch_mem(128 << 20); - let vcpus_exit_evt = EventFd::new(libc::EFD_NONBLOCK) - .map_err(VmmError::EventFd) - .map_err(StartMicrovmError::Internal) - .unwrap(); - let kvm = Kvm::new(vec![]).unwrap(); let mut vm = Vm::new(&kvm).unwrap(); vm.memory_init(&guest_memory).unwrap(); @@ -1153,15 +1101,7 @@ pub(crate) mod tests { ) .unwrap(); - #[cfg(target_arch = "x86_64")] - setup_interrupt_controller(&mut vm).unwrap(); - - #[cfg(target_arch = "aarch64")] - { - let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); - let _vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); - setup_interrupt_controller(&mut vm, 1).unwrap(); - } + let (_, vcpus_exit_evt) = vm.create_vcpus(1).unwrap(); Vmm { events_observer: Some(std::io::stdin()), @@ -1380,24 +1320,6 @@ pub(crate) mod tests { ); } - #[test] - fn test_create_vcpus() { - let vcpu_count = 2; - let guest_memory = arch_mem(128 << 20); - - let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); - #[allow(unused_mut)] - let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_memory).unwrap(); - let evfd = EventFd::new(libc::EFD_NONBLOCK).unwrap(); - - #[cfg(target_arch = "x86_64")] - setup_interrupt_controller(&mut vm).unwrap(); - - let vcpu_vec = create_vcpus(&vm, vcpu_count, &evfd).unwrap(); - assert_eq!(vcpu_vec.len(), vcpu_count as usize); - } - #[test] fn test_attach_net_devices() { let mut event_manager = EventManager::new().expect("Unable to create EventManager"); diff --git a/src/vmm/src/device_manager/legacy.rs b/src/vmm/src/device_manager/legacy.rs index 8526d3c2901..eee2f86dc83 100644 --- a/src/vmm/src/device_manager/legacy.rs +++ b/src/vmm/src/device_manager/legacy.rs @@ -248,8 +248,8 @@ mod tests { #[test] fn test_register_legacy_devices() { - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - crate::builder::setup_interrupt_controller(&mut vm).unwrap(); + let (_, vm, _) = setup_vm_with_memory(0x1000); + vm.setup_irqchip().unwrap(); let mut ldm = PortIODeviceManager::new( Arc::new(Mutex::new(BusDevice::Serial(SerialDevice { serial: Serial::with_events( diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index d35c8b36650..e4e5e68dcb8 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -549,7 +549,7 @@ mod tests { use crate::test_utils::multi_region_mem; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; - use crate::{builder, Vm}; + use crate::Vm; const QUEUE_SIZES: &[u16] = &[64]; @@ -673,9 +673,9 @@ mod tests { let mut cmdline = kernel_cmdline::Cmdline::new(4096).unwrap(); let dummy = Arc::new(Mutex::new(DummyDevice::new())); #[cfg(target_arch = "x86_64")] - builder::setup_interrupt_controller(&mut vm).unwrap(); + vm.setup_irqchip().unwrap(); #[cfg(target_arch = "aarch64")] - builder::setup_interrupt_controller(&mut vm, 1).unwrap(); + vm.setup_irqchip(1).unwrap(); device_manager .register_virtio_test_device( @@ -702,9 +702,9 @@ mod tests { let mut cmdline = kernel_cmdline::Cmdline::new(4096).unwrap(); #[cfg(target_arch = "x86_64")] - builder::setup_interrupt_controller(&mut vm).unwrap(); + vm.setup_irqchip().unwrap(); #[cfg(target_arch = "aarch64")] - builder::setup_interrupt_controller(&mut vm, 1).unwrap(); + vm.setup_irqchip(1).unwrap(); for _i in crate::arch::IRQ_BASE..=crate::arch::IRQ_MAX { device_manager @@ -756,9 +756,9 @@ mod tests { let mem_clone = guest_mem.clone(); #[cfg(target_arch = "x86_64")] - builder::setup_interrupt_controller(&mut vm).unwrap(); + vm.setup_irqchip().unwrap(); #[cfg(target_arch = "aarch64")] - builder::setup_interrupt_controller(&mut vm, 1).unwrap(); + vm.setup_irqchip(1).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 593ae7bc5ea..a059803ba97 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -37,6 +37,18 @@ impl ArchVm { }) } + pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + Ok(()) + } + + pub(super) fn arch_post_create_vcpus(&mut self, nr_vcpus: u8) -> Result<(), ArchVmError> { + // On aarch64, the vCPUs need to be created (i.e call KVM_CREATE_VCPU) before setting up the + // IRQ chip because the `KVM_CREATE_VCPU` ioctl will return error if the IRQCHIP + // was already initialized. + // Search for `kvm_arch_vcpu_create` in arch/arm/kvm/arm.c. + self.setup_irqchip(nr_vcpus) + } + /// Creates the GIC (Global Interrupt Controller). pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), ArchVmError> { self.irqchip_handle = Some( diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index df4e72c2e95..c34ac3c7d52 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -7,6 +7,7 @@ use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; use kvm_ioctls::VmFd; +use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] use crate::utils::u64_to_usize; @@ -21,10 +22,13 @@ mod arch; pub use arch::{ArchVm as Vm, ArchVmError, VmState}; +use crate::vstate::vcpu::VcpuError; +use crate::Vcpu; + /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work #[rustfmt::skip] -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +#[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum VmError { /// Cannot set the memory regions: {0} SetUserMemoryRegion(kvm_ioctls::Error), @@ -34,10 +38,34 @@ pub enum VmError { VmSetup(kvm_ioctls::Error), /// {0} Arch(#[from] ArchVmError), + /// Error during eventfd operations: {0} + EventFd(std::io::Error), + /// Failed to create vcpu: {0} + CreateVcpu(VcpuError), } /// Contains Vm functions that are usable across CPU architectures impl Vm { + /// Creates the specified number of [`Vcpu`]s. + /// + /// The returned [`EventFd`] is written to whenever any of the vcpus exit. + pub fn create_vcpus(&mut self, vcpu_count: u8) -> Result<(Vec, EventFd), VmError> { + self.arch_pre_create_vcpus(vcpu_count)?; + + let exit_evt = EventFd::new(libc::EFD_NONBLOCK).map_err(VmError::EventFd)?; + + let mut vcpus = Vec::with_capacity(vcpu_count as usize); + for cpu_idx in 0..vcpu_count { + let exit_evt = exit_evt.try_clone().map_err(VmError::EventFd)?; + let vcpu = Vcpu::new(cpu_idx, self, exit_evt).map_err(VmError::CreateVcpu)?; + vcpus.push(vcpu); + } + + self.arch_post_create_vcpus(vcpu_count)?; + + Ok((vcpus, exit_evt)) + } + /// Initializes the guest memory. pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { self.set_kvm_memory_regions(guest_mem)?; @@ -88,7 +116,7 @@ impl Vm { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::test_utils::single_region_mem; + use crate::test_utils::{arch_mem, single_region_mem}; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; @@ -139,4 +167,19 @@ pub(crate) mod tests { "Cannot set the memory regions: Invalid argument (os error 22)" ); } + + #[test] + fn test_create_vcpus() { + let vcpu_count = 2; + let guest_memory = arch_mem(128 << 20); + + let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); + #[allow(unused_mut)] + let mut vm = Vm::new(&kvm).unwrap(); + vm.memory_init(&guest_memory).unwrap(); + + let (vcpu_vec, _) = vm.create_vcpus(vcpu_count).unwrap(); + + assert_eq!(vcpu_vec.len(), vcpu_count as usize); + } } diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 19af125e5ec..483339521dc 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -59,6 +59,15 @@ impl ArchVm { Ok(ArchVm { fd, msrs_to_save }) } + pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS` + self.setup_irqchip() + } + + pub(super) fn arch_post_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + Ok(()) + } + /// Restores the KVM VM state. /// /// # Errors From d4394dd1f687e9c832cb2bfb89a0061f25ed59f6 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 31 Jan 2025 14:05:34 +0000 Subject: [PATCH 233/464] refactor(test): use vm.create_vcpus() instead of open coding it Instead of doing the irqchip dance inside unit testing code, just call vm.create_vcpus, which does it for us. Signed-off-by: Patrick Roy --- src/vmm/src/device_manager/mmio.rs | 3 +++ src/vmm/src/vstate/vcpu/mod.rs | 16 ++++------------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index e4e5e68dcb8..dc814de9766 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -660,6 +660,7 @@ mod tests { } #[test] + #[cfg_attr(target_arch = "x86_64", allow(unused_mut))] fn test_register_virtio_device() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); @@ -690,6 +691,7 @@ mod tests { } #[test] + #[cfg_attr(target_arch = "x86_64", allow(unused_mut))] fn test_register_too_many_devices() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); @@ -745,6 +747,7 @@ mod tests { } #[test] + #[cfg_attr(target_arch = "x86_64", allow(unused_mut))] fn test_device_info() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 363964b6edc..9ad8f867145 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -932,20 +932,12 @@ pub(crate) mod tests { pub(crate) fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, Vcpu, GuestMemoryMmap) { let (kvm, mut vm, gm) = setup_vm_with_memory(mem_size); - let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); + let (mut vcpus, _) = vm.create_vcpus(1).unwrap(); + let mut vcpu = vcpus.remove(0); #[cfg(target_arch = "aarch64")] - let vcpu = { - let mut vcpu = Vcpu::new(1, &vm, exit_evt).unwrap(); - vcpu.kvm_vcpu.init(&[]).unwrap(); - vm.setup_irqchip(1).unwrap(); - vcpu - }; - #[cfg(target_arch = "x86_64")] - let vcpu = { - vm.setup_irqchip().unwrap(); - Vcpu::new(1, &vm, exit_evt).unwrap() - }; + vcpu.kvm_vcpu.init(&[]).unwrap(); + (kvm, vm, vcpu, gm) } From 73e86de47485ff6ffae7558c2e0712af9c1c3633 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 31 Jan 2025 14:59:10 +0000 Subject: [PATCH 234/464] refactor(test): be more consistent in using vm-creation utilities We have some utility functions for creating dummy VMs/etc. in unittests, so let's try to use them instead of copy-pasting the same few lines around. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 8 +++----- src/vmm/src/vstate/vm/mod.rs | 9 ++------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index b450ce50b10..3f6847aa8dc 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -1015,7 +1015,7 @@ pub(crate) mod tests { use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_RNG}; use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; - use crate::test_utils::{arch_mem, single_region_mem, single_region_mem_at}; + use crate::test_utils::{single_region_mem, single_region_mem_at}; use crate::vmm_config::balloon::{BalloonBuilder, BalloonDeviceConfig, BALLOON_DEV_ID}; use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE; use crate::vmm_config::drive::{BlockBuilder, BlockDeviceConfig}; @@ -1023,6 +1023,7 @@ pub(crate) mod tests { use crate::vmm_config::net::{NetBuilder, NetworkInterfaceConfig}; use crate::vmm_config::vsock::tests::default_config; use crate::vmm_config::vsock::{VsockBuilder, VsockDeviceConfig}; + use crate::vstate::vm::tests::setup_vm_with_memory; #[derive(Debug)] pub(crate) struct CustomBlockConfig { @@ -1078,11 +1079,8 @@ pub(crate) mod tests { } pub(crate) fn default_vmm() -> Vmm { - let guest_memory = arch_mem(128 << 20); + let (kvm, mut vm, guest_memory) = setup_vm_with_memory(128 << 20); - let kvm = Kvm::new(vec![]).unwrap(); - let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_memory).unwrap(); let mmio_device_manager = MMIODeviceManager::new(); let acpi_device_manager = ACPIDeviceManager::new(); #[cfg(target_arch = "x86_64")] diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index c34ac3c7d52..3277564f725 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -116,7 +116,7 @@ impl Vm { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::test_utils::{arch_mem, single_region_mem}; + use crate::test_utils::single_region_mem; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; @@ -171,12 +171,7 @@ pub(crate) mod tests { #[test] fn test_create_vcpus() { let vcpu_count = 2; - let guest_memory = arch_mem(128 << 20); - - let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); - #[allow(unused_mut)] - let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_memory).unwrap(); + let (_, mut vm, _) = setup_vm_with_memory(128 << 20); let (vcpu_vec, _) = vm.create_vcpus(vcpu_count).unwrap(); From 56b497948efa10c9e8b668fef9f9b1cf8ac1380d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Feb 2025 11:58:33 +0000 Subject: [PATCH 235/464] refactor: avoid an unwrap in set_kvm_memory_regions There's no need to use the GuestMemoryMmap to resolve the pointer to the start of the GuestMemoryRegion by resolving the guest physical address it starts at - because we literally store that pointer inside the GuestMemoryRegion, so can just use that. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vm/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 3277564f725..9c1395e07d7 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -95,8 +95,7 @@ impl Vm { slot, guest_phys_addr: region.start_addr().raw_value(), memory_size: region.len(), - // It's safe to unwrap because the guest address is valid. - userspace_addr: guest_mem.get_host_address(region.start_addr()).unwrap() as u64, + userspace_addr: region.as_ptr() as u64, flags, }; From f9269aa010e7bbafc81dabd93b75216dfe0ac42c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Feb 2025 14:09:57 +0000 Subject: [PATCH 236/464] refactor: move KVM_SET_TSS_ADDR call into Vm::arch_create Since we issue this ioctl with a constant address, it doesn't really matter _when_ we do it. Internally, it causes a hidden memslot of size 3 pages to be created. If we create it _after_ all other memslots, then this ioctl can fail with EEXIST if it would overlap some pre-existing memslot. Now, instead the creation of the overlapping memslot would fail with EEXIST. But this is a moot point, because if Firecracker ever tried to create a memslot that overlaps this one, something is fundamentally broken. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vm/mod.rs | 10 +--------- src/vmm/src/vstate/vm/x86_64.rs | 7 +++++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 9c1395e07d7..7d9d3e04ba9 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -9,8 +9,6 @@ use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; -#[cfg(target_arch = "x86_64")] -use crate::utils::u64_to_usize; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; #[cfg(target_arch = "x86_64")] @@ -68,13 +66,7 @@ impl Vm { /// Initializes the guest memory. pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { - self.set_kvm_memory_regions(guest_mem)?; - #[cfg(target_arch = "x86_64")] - self.fd - .set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) - .map_err(VmError::VmSetup)?; - - Ok(()) + self.set_kvm_memory_regions(guest_mem) } pub(crate) fn set_kvm_memory_regions( diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 483339521dc..5dd904a15f5 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -11,6 +11,7 @@ use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; use crate::arch::x86_64::msr::MsrError; +use crate::utils::u64_to_usize; use crate::vstate::vm::VmError; /// Error type for [`Vm::restore_state`] @@ -42,6 +43,8 @@ pub enum ArchVmError { VmSetIrqChip(kvm_ioctls::Error), /// Failed to get MSR index list to save into snapshots: {0} GetMsrsToSave(MsrError), + /// Failed during KVM_SET_TSS_ADDRESS: {0} + SetTssAddress(kvm_ioctls::Error), } /// Structure representing the current architecture's understand of what a "virtual machine" is. @@ -56,6 +59,10 @@ impl ArchVm { pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; + + fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) + .map_err(ArchVmError::SetTssAddress)?; + Ok(ArchVm { fd, msrs_to_save }) } From 76d90953320d1dce3daa0569698faf02440cc6d7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 7 Feb 2025 17:17:03 +0000 Subject: [PATCH 237/464] fix: delete never constructed error enum variants All of these were dead code (but the compiler isn't able to tell us because the vmm crate is a library crate where everything is `pub`, and it doesn't know that no downstream users outside of the `firecracker` crate exist, and that everything that's not used in `firecracker` is dead code). Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 13 ------------- src/vmm/src/vstate/memory.rs | 4 ---- src/vmm/src/vstate/vm/mod.rs | 2 -- src/vmm/src/vstate/vm/x86_64.rs | 4 ---- 4 files changed, 23 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 05529107b6b..d62ffc84600 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -114,18 +114,10 @@ pub struct GuestRegionUffdMapping { /// Errors related to saving and restoring Microvm state. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum MicrovmStateError { - /// Compatibility checks failed: {0} - IncompatibleState(String), - /// Provided MicroVM state is invalid. - InvalidInput, /// Operation not allowed: {0} NotAllowed(String), /// Cannot restore devices: {0} RestoreDevices(DevicePersistError), - /// Cannot restore Vcpu state: {0} - RestoreVcpuState(vstate::vcpu::VcpuError), - /// Cannot restore Vm state: {0} - RestoreVmState(vstate::vm::VmError), /// Cannot save Vcpu state: {0} SaveVcpuState(vstate::vcpu::VcpuError), /// Cannot save Vm state: {0} @@ -142,9 +134,6 @@ pub enum MicrovmStateError { pub enum CreateSnapshotError { /// Cannot get dirty bitmap: {0} DirtyBitmap(VmmError), - #[rustfmt::skip] - /// Cannot translate microVM version to snapshot data version - UnsupportedVersion, /// Cannot write memory file: {0} Memory(MemoryError), /// Cannot perform {0} on the memory backing file: {1} @@ -155,8 +144,6 @@ pub enum CreateSnapshotError { SerializeMicrovmState(crate::snapshot::SnapshotError), /// Cannot perform {0} on the snapshot backing file: {1} SnapshotBackingFile(&'static str, io::Error), - /// Size mismatch when writing diff snapshot on top of base layer: base layer size is {0} but diff layer is size {1}. - SnapshotBackingFileLengthMismatch(u64, u64), } /// Snapshot version diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 23ce07d06b9..228c8b8f062 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -36,10 +36,6 @@ pub type GuestMmapRegion = vm_memory::MmapRegion>; /// Errors associated with dumping guest memory to file. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum MemoryError { - /// Cannot create memory: {0} - CreateMemory(VmMemoryError), - /// Cannot create memory region: {0} - CreateRegion(MmapRegionError), /// Cannot fetch system's page size: {0} PageSize(errno::Error), /// Cannot dump memory: {0} diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 7d9d3e04ba9..c9c0e7e7c2f 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -32,8 +32,6 @@ pub enum VmError { SetUserMemoryRegion(kvm_ioctls::Error), /// Cannot open the VM file descriptor: {0} VmFd(kvm_ioctls::Error), - /// Cannot configure the microvm: {0} - VmSetup(kvm_ioctls::Error), /// {0} Arch(#[from] ArchVmError), /// Error during eventfd operations: {0} diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 5dd904a15f5..f44e825b6f9 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -35,10 +35,6 @@ pub enum ArchVmError { VmGetClock(kvm_ioctls::Error), /// Failed to get KVM vm irqchip: {0} VmGetIrqChip(kvm_ioctls::Error), - /// Failed to set KVM vm pit state: {0} - VmSetPit2(kvm_ioctls::Error), - /// Failed to set KVM vm clock: {0} - VmSetClock(kvm_ioctls::Error), /// Failed to set KVM vm irqchip: {0} VmSetIrqChip(kvm_ioctls::Error), /// Failed to get MSR index list to save into snapshots: {0} From 538702bbf87574619b26ace350ff6faaec3cca6e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Feb 2025 16:57:42 +0000 Subject: [PATCH 238/464] fix(test): dont drop guest memory before using it Dropping a GuestMemoryMmap causes the memory to get unmapped, so if we try to KVM_RUN after dropping it, we'll just get EFAULT. Admittedly no idea how we didn't run into this issue before. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vcpu/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 9ad8f867145..b120a9f2c07 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -969,7 +969,7 @@ pub(crate) mod tests { entry_addr.unwrap().kernel_load } - fn vcpu_configured_for_boot() -> (VcpuHandle, vmm_sys_util::eventfd::EventFd) { + fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd, GuestMemoryMmap) { Vcpu::register_kick_signal_handler(); // Need enough mem to boot linux. let mem_size = 64 << 20; @@ -1021,7 +1021,7 @@ pub(crate) mod tests { // Wait for vCPUs to initialize their TLS before moving forward. barrier.wait(); - (vcpu_handle, vcpu_exit_evt) + (vcpu_handle, vcpu_exit_evt, vm_mem) } #[test] @@ -1034,7 +1034,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_tls() { - let (_, _, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _mem) = setup_vcpu(0x1000); // Running on the TLS vcpu should fail before we actually initialize it. unsafe { @@ -1075,7 +1075,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_kick() { Vcpu::register_kick_signal_handler(); - let (_, vm, mut vcpu, _) = setup_vcpu(0x1000); + let (_, vm, mut vcpu, _mem) = setup_vcpu(0x1000); let mut kvm_run = kvm_ioctls::KvmRunWrapper::mmap_from_fd(&vcpu.kvm_vcpu.fd, vm.fd().run_size()) @@ -1130,7 +1130,7 @@ pub(crate) mod tests { #[test] fn test_immediate_exit_shortcircuits_execution() { - let (_, _, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu, _mem) = setup_vcpu(0x1000); vcpu.kvm_vcpu.fd.set_kvm_immediate_exit(1); // Set a dummy value to be returned by the emulate call @@ -1155,7 +1155,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_pause_resume() { - let (vcpu_handle, vcpu_exit_evt) = vcpu_configured_for_boot(); + let (vcpu_handle, vcpu_exit_evt, _mem) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1187,7 +1187,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_save_state_events() { - let (vcpu_handle, _vcpu_exit_evt) = vcpu_configured_for_boot(); + let (vcpu_handle, _vcpu_exit_evt, _mem) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1220,7 +1220,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_dump_cpu_config() { - let (vcpu_handle, _) = vcpu_configured_for_boot(); + let (vcpu_handle, _, _mem) = vcpu_configured_for_boot(); // Queue a DumpCpuConfig event, expect a DumpedCpuConfig response. vcpu_handle From 15699a3d9bc2373a16a2aca4f517dda30f5f0917 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Tue, 14 Jan 2025 12:07:36 +0000 Subject: [PATCH 239/464] feat: AMD support larger extended function entries Removed the extended function entry normalisation step from AMD CPUs. We will now pass through the value provided by KVM or set through a CPU template. This now mirrors the behaviour of Intel. On newer AMD chips and newer kernels we are now able to pass through features which were previously out of range. Signed-off-by: Jack Thomson --- docs/cpu_templates/cpuid-normalization.md | 19 +++++++++---------- .../cpu_config/x86_64/cpuid/amd/normalize.rs | 18 ------------------ .../fingerprint_AMD_MILAN_6.1host.json | 4 ++-- .../functional/test_cpu_template_helper.py | 5 ++++- 4 files changed, 15 insertions(+), 31 deletions(-) diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index 2d7b3f40c81..3e6e54bd515 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -42,13 +42,12 @@ See also: [boot protocol settings](boot-protocol.md) ## AMD-specifc CPUID normalization -| Description | Leaf | Subleaf | Register | Bits | -| ---------------------------------------------------- | :--------------------------------: | :-----: | :----------------: | :---: | -| Set IA32_ARCH_CAPABILITIES MSR as not present | 0x7 | - | EDX | 29 | -| Update largest extended function entry to 0x8000001f | 0x80000000 | - | EAX | 31:0 | -| Set topology extension bit | 0x80000001 | - | ECX | 22 | -| Update brand string with a default AMD value | 0x80000002, 0x80000003, 0x80000004 | - | EAX, EBX, ECX, EDX | all | -| Update number of physical threads | 0x80000008 | - | ECX | 7:0 | -| Update APIC ID size | 0x80000008 | - | ECX | 15:12 | -| Update cache topology information | 0x8000001d | all | all | all | -| Update extended APIC ID | 0x8000001e | - | EAX, EBX, ECX | all | +| Description | Leaf | Subleaf | Register | Bits | +| --------------------------------------------- | :--------------------------------: | :-----: | :----------------: | :---: | +| Set IA32_ARCH_CAPABILITIES MSR as not present | 0x7 | - | EDX | 29 | +| Set topology extension bit | 0x80000001 | - | ECX | 22 | +| Update brand string with a default AMD value | 0x80000002, 0x80000003, 0x80000004 | - | EAX, EBX, ECX, EDX | all | +| Update number of physical threads | 0x80000008 | - | ECX | 7:0 | +| Update APIC ID size | 0x80000008 | - | ECX | 15:12 | +| Update cache topology information | 0x8000001d | all | all | all | +| Update extended APIC ID | 0x8000001e | - | EAX, EBX, ECX | all | diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs index 5a682441e8d..f2f46b54c3d 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs @@ -104,7 +104,6 @@ impl super::AmdCpuid { ) -> Result<(), NormalizeCpuidError> { self.passthrough_cache_topology()?; self.update_structured_extended_entry()?; - self.update_largest_extended_fn_entry()?; self.update_extended_feature_fn_entry()?; self.update_amd_feature_entry(cpu_count)?; self.update_extended_cache_topology_entry(cpu_count, cpus_per_core)?; @@ -181,23 +180,6 @@ impl super::AmdCpuid { Ok(()) } - /// Update largest extended fn entry. - #[allow(clippy::unwrap_used, clippy::unwrap_in_result)] - fn update_largest_extended_fn_entry(&mut self) -> Result<(), NormalizeCpuidError> { - // KVM sets the largest extended function to 0x80000000. Change it to 0x8000001f - // Since we also use the leaf 0x8000001d (Extended Cache Topology). - let leaf_80000000 = self - .get_mut(&CpuidKey::leaf(0x80000000)) - .ok_or(NormalizeCpuidError::MissingLeaf0x80000000)?; - - // Largest extended function. The largest CPUID extended function input value supported by - // the processor implementation. - // - // l_func_ext: 0..32, - set_range(&mut leaf_80000000.result.eax, 0..32, 0x8000_001f).unwrap(); - Ok(()) - } - /// Updated extended feature fn entry. fn update_extended_feature_fn_entry(&mut self) -> Result<(), NormalizeCpuidError> { // set the Topology Extension bit since we use the Extended Cache Topology leaf diff --git a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json index e0330895de7..56f406560ee 100644 --- a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json @@ -543,7 +543,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b10000000000000000000000000011111" + "bitmap": "0b10000000000000000000000000100001" }, { "register": "ebx", @@ -1546,4 +1546,4 @@ } ] } -} \ No newline at end of file +} diff --git a/tests/integration_tests/functional/test_cpu_template_helper.py b/tests/integration_tests/functional/test_cpu_template_helper.py index 3e57cca644a..1b1c2478da3 100644 --- a/tests/integration_tests/functional/test_cpu_template_helper.py +++ b/tests/integration_tests/functional/test_cpu_template_helper.py @@ -146,13 +146,14 @@ def build_cpu_config_dict(cpu_config_path): # https://github.com/torvalds/linux/commit/8765d75329a386dd7742f94a1ea5fdcdea8d93d0 (0x8000001B, 0x0), (0x8000001C, 0x0), - (0x8000001F, 0x0), # CPUID.80860000h is a Transmeta-specific leaf. (0x80860000, 0x0), # CPUID.C0000000h is a Centaur-specific leaf. (0xC0000000, 0x0), ] +# An upper range of CPUID leaves which are not supported by our kernels +UNAVAILABLE_CPUID_UPPER_RANGE = range(0x8000001F, 0x80000029) # Dictionary of CPUID bitmasks that should not be tested due to its mutability. CPUID_EXCEPTION_LIST = { @@ -281,6 +282,8 @@ def test_cpu_config_dump_vs_actual( for key, actual in actual_cpu_config["cpuid"].items(): if (key[0], key[1]) in UNAVAILABLE_CPUID_ON_DUMP_LIST: continue + if key[0] in UNAVAILABLE_CPUID_UPPER_RANGE: + continue if key not in dump_cpu_config["cpuid"]: keys_not_in_dump[key] = actual_cpu_config["cpuid"][key] continue From 26a3a1ea2b43025bd6167a2ae9ee3f2ef2cf5c68 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 19 Feb 2025 14:54:38 +0000 Subject: [PATCH 240/464] doc: Update changelog Add entry for the removal of extended function entry normalisation. Signed-off-by: Jack Thomson --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7bf7d4c014..ed06b7e2323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,10 @@ and this project adheres to - [#5045](https://github.com/firecracker-microvm/firecracker/pull/5045): Fixed an issue where firecracker intermittently receives SIGHUP when using jailer with `--new-pid-ns` but without `--daemonize`. +- [#4995](https://github.com/firecracker-microvm/firecracker/pull/4995): + Firecracker no longer overwrites CPUID leaf 0x80000000 when running AMD + hardware, meaning the guest can now discover a greater range of CPUID leaves + in the extended function range (this range is host kernel dependent). ## [1.10.1] From 80c5596ecbd3fa1c92588610ac9fa93ee4f81fd5 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 21 Feb 2025 12:46:10 +0000 Subject: [PATCH 241/464] refactor: Rename VmError::VmFd to VmError::CreateVm The error variant is used when creating a new VM from KVM FD via KVM_CREATE_VM call. On success, VM FD is returned. The previous error message doesn't tell a lie but is a bit unintuitive. Signed-off-by: Takahiro Itazuri --- src/vmm/src/vstate/vm/aarch64.rs | 2 +- src/vmm/src/vstate/vm/mod.rs | 4 ++-- src/vmm/src/vstate/vm/x86_64.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index a059803ba97..60ebf4d87d1 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -30,7 +30,7 @@ pub enum ArchVmError { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &Kvm) -> Result { - let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; + let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?; Ok(ArchVm { fd, irqchip_handle: None, diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index c9c0e7e7c2f..f8345d2ab02 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -30,8 +30,8 @@ use crate::Vcpu; pub enum VmError { /// Cannot set the memory regions: {0} SetUserMemoryRegion(kvm_ioctls::Error), - /// Cannot open the VM file descriptor: {0} - VmFd(kvm_ioctls::Error), + /// Failed to create VM: {0} + CreateVm(kvm_ioctls::Error), /// {0} Arch(#[from] ArchVmError), /// Error during eventfd operations: {0} diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index f44e825b6f9..54b1fe41723 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -53,7 +53,7 @@ pub struct ArchVm { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { - let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?; + let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?; let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) From 1e1d8ae9b0f851499921b76dbe6358ab7829705b Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 21 Feb 2025 13:36:14 +0000 Subject: [PATCH 242/464] fix: Retry KVM_CREATE_VM on EINTR It is known that KVM_CREATE_VM fails with EINTR on heavily loaded machines with many VMs. It might be a kernel bug but apparently has not been fixed. To mitigate it, QEMU does an infinitely retry on EINTR. Similar, do retries up to 5 times. Signed-off-by: Takahiro Itazuri --- src/vmm/src/vstate/vm/aarch64.rs | 2 +- src/vmm/src/vstate/vm/mod.rs | 37 ++++++++++++++++++++++++++++++++ src/vmm/src/vstate/vm/x86_64.rs | 3 ++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 60ebf4d87d1..6aee3d8e609 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -30,7 +30,7 @@ pub enum ArchVmError { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &Kvm) -> Result { - let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?; + let fd = Self::create_vm(kvm)?; Ok(ArchVm { fd, irqchip_handle: None, diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index f8345d2ab02..5f4c7bb53c5 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -9,6 +9,7 @@ use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; +use crate::logger::info; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; #[cfg(target_arch = "x86_64")] @@ -42,6 +43,42 @@ pub enum VmError { /// Contains Vm functions that are usable across CPU architectures impl Vm { + fn create_vm(kvm: &crate::vstate::kvm::Kvm) -> Result { + // It is known that KVM_CREATE_VM occasionally fails with EINTR on heavily loaded machines + // with many VMs. + // + // The behavior itself that KVM_CREATE_VM can return EINTR is intentional. This is because + // the KVM_CREATE_VM path includes mm_take_all_locks() that is CPU intensive and all CPU + // intensive syscalls should check for pending signals and return EINTR immediately to allow + // userland to remain interactive. + // https://lists.nongnu.org/archive/html/qemu-devel/2014-01/msg01740.html + // + // However, it is empirically confirmed that, even though there is no pending signal, + // KVM_CREATE_VM returns EINTR. + // https://lore.kernel.org/qemu-devel/8735e0s1zw.wl-maz@kernel.org/ + // + // To mitigate it, QEMU does an inifinite retry on EINTR that greatly improves reliabiliy: + // - https://github.com/qemu/qemu/commit/94ccff133820552a859c0fb95e33a539e0b90a75 + // - https://github.com/qemu/qemu/commit/bbde13cd14ad4eec18529ce0bf5876058464e124 + // + // Similarly, we do retries up to 5 times. Although Firecracker clients are also able to + // retry, they have to start Firecracker from scratch. Doing retries in Firecracker makes + // recovery faster and improves reliability. + const MAX_ATTEMPTS: u32 = 5; + for attempt in 1..=MAX_ATTEMPTS { + match kvm.fd.create_vm() { + Ok(fd) => return Ok(fd), + Err(e) if e.errno() == libc::EINTR && attempt < MAX_ATTEMPTS => { + info!("Attempt #{attempt} of KVM_CREATE_VM returned EINTR"); + // Exponential backoff (1us, 2us, 4us, and 8us => 15us in total) + std::thread::sleep(std::time::Duration::from_micros(2u64.pow(attempt - 1))); + } + Err(e) => return Err(VmError::CreateVm(e)), + } + } + unreachable!(); + } + /// Creates the specified number of [`Vcpu`]s. /// /// The returned [`EventFd`] is written to whenever any of the vcpus exit. diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index 54b1fe41723..c68e3c3fb1c 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -53,7 +53,8 @@ pub struct ArchVm { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { - let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?; + let fd = Self::create_vm(kvm)?; + let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) From a7c90b74e8424880f4da7fe0d9c49cf14eeae3a5 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 24 Feb 2025 12:57:36 +0000 Subject: [PATCH 243/464] chore: Add CHANGELOG entry for retrying KVM_CREATE_VM on EINTR No reason not to have it in CHANGELOG. Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed06b7e2323..673a1b7a88d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,9 @@ and this project adheres to Firecracker no longer overwrites CPUID leaf 0x80000000 when running AMD hardware, meaning the guest can now discover a greater range of CPUID leaves in the extended function range (this range is host kernel dependent). +- [#5046](https://github.com/firecracker-microvm/firecracker/pull/5046): Retry + KVM_CREATE_VM on EINTR that occasionally happen on heavily loaded hosts to + improve reliability of microVM creation. ## [1.10.1] From 3fb9a2a21115bcd9a052bb9ba275daec6eb55f8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:42:12 +0000 Subject: [PATCH 244/464] build(deps): Bump the firecracker group with 18 updates Bumps the firecracker group with 18 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.18` | `0.8.20` | | [clap](https://github.com/clap-rs/clap) | `4.5.29` | `4.5.31` | | [uuid](https://github.com/uuid-rs/uuid) | `1.13.1` | `1.14.0` | | [libc](https://github.com/rust-lang/libc) | `0.2.169` | `0.2.170` | | [serde](https://github.com/serde-rs/serde) | `1.0.217` | `1.0.218` | | [serde_json](https://github.com/serde-rs/json) | `1.0.138` | `1.0.139` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.217` | `1.0.218` | | [log](https://github.com/rust-lang/log) | `0.4.25` | `0.4.26` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.12.2` | `1.12.4` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.25.1` | `0.26.0` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.14` | `1.2.15` | | [clap_builder](https://github.com/clap-rs/clap) | `4.5.29` | `4.5.31` | | [either](https://github.com/rayon-rs/either) | `1.13.0` | `1.14.0` | | [inout](https://github.com/RustCrypto/utils) | `0.1.3` | `0.1.4` | | [typenum](https://github.com/paholg/typenum) | `1.17.0` | `1.18.0` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.16` | `1.0.17` | | [uuid-macro-internal](https://github.com/uuid-rs/uuid) | `1.13.1` | `1.14.0` | | [winnow](https://github.com/winnow-rs/winnow) | `0.7.2` | `0.7.3` | Updates `zerocopy` from 0.8.18 to 0.8.20 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.18...v0.8.20) Updates `clap` from 4.5.29 to 4.5.31 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.29...v4.5.31) Updates `uuid` from 1.13.1 to 1.14.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.13.1...v1.14.0) Updates `libc` from 0.2.169 to 0.2.170 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.170/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.169...0.2.170) Updates `serde` from 1.0.217 to 1.0.218 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218) Updates `serde_json` from 1.0.138 to 1.0.139 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.138...v1.0.139) Updates `serde_derive` from 1.0.217 to 1.0.218 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218) Updates `log` from 0.4.25 to 0.4.26 - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.25...0.4.26) Updates `aws-lc-rs` from 1.12.2 to 1.12.4 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.12.2...v1.12.4) Updates `aws-lc-sys` from 0.25.1 to 0.26.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.25.1...aws-lc-sys/v0.26.0) Updates `cc` from 1.2.14 to 1.2.15 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15) Updates `clap_builder` from 4.5.29 to 4.5.31 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.29...v4.5.31) Updates `either` from 1.13.0 to 1.14.0 - [Commits](https://github.com/rayon-rs/either/compare/1.13.0...1.14.0) Updates `inout` from 0.1.3 to 0.1.4 - [Commits](https://github.com/RustCrypto/utils/compare/inout-v0.1.3...inout-v0.1.4) Updates `typenum` from 1.17.0 to 1.18.0 - [Release notes](https://github.com/paholg/typenum/releases) - [Changelog](https://github.com/paholg/typenum/blob/main/CHANGELOG.md) - [Commits](https://github.com/paholg/typenum/compare/v1.17.0...v1.18.0) Updates `unicode-ident` from 1.0.16 to 1.0.17 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.16...1.0.17) Updates `uuid-macro-internal` from 1.13.1 to 1.14.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.13.1...v1.14.0) Updates `winnow` from 0.7.2 to 0.7.3 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.7.2...v0.7.3) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: either dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: inout dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: typenum dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 88 +++++++++++++++--------------- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 4 +- src/cpu-template-helper/Cargo.toml | 8 +-- src/firecracker/Cargo.toml | 14 ++--- src/jailer/Cargo.toml | 2 +- src/log-instrument/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 10 ++-- src/snapshot-editor/Cargo.toml | 4 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 12 ++-- 12 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2826568ba8e..a667da093cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.11", "vm-memory", - "zerocopy 0.8.18", + "zerocopy 0.8.20", ] [[package]] @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.2" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" +checksum = "4cd755adf9707cf671e31d944a189be3deaaeee11c8bc1d669bb8022ac90fbd0" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac4f13dad353b209b34cbec082338202cbc01c8f00336b55c750c13ac91f8f" +checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" dependencies = [ "bindgen 0.69.5", "cc", @@ -260,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.14" +version = "1.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" dependencies = [ "jobserver", "libc", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.29" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" +checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.29" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" +checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" dependencies = [ "anstream", "anstyle", @@ -544,9 +544,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" [[package]] name = "env_filter" @@ -754,9 +754,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array", ] @@ -860,9 +860,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libloading" @@ -891,9 +891,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.25" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" dependencies = [ "serde", ] @@ -1096,7 +1096,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.0", - "zerocopy 0.8.18", + "zerocopy 0.8.20", ] [[package]] @@ -1135,7 +1135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.18", + "zerocopy 0.8.20", ] [[package]] @@ -1233,7 +1233,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.11", - "zerocopy 0.8.18", + "zerocopy 0.8.20", ] [[package]] @@ -1247,18 +1247,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", @@ -1267,9 +1267,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ "itoa", "memchr", @@ -1435,9 +1435,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unarray" @@ -1447,9 +1447,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "unicode-xid" @@ -1516,9 +1516,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" +checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" dependencies = [ "getrandom 0.3.1", "rand 0.9.0", @@ -1527,9 +1527,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d28dd23acb5f2fa7bd2155ab70b960e770596b3bb6395119b40476c3655dfba4" +checksum = "1be57878a5f7e409a1a82be6691922b11e59687a168205b1f21b087c4acdd194" dependencies = [ "proc-macro2", "quote", @@ -1631,7 +1631,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.18", + "zerocopy 0.8.20", ] [[package]] @@ -1789,9 +1789,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] @@ -1817,11 +1817,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.18" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" +checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" dependencies = [ - "zerocopy-derive 0.8.18", + "zerocopy-derive 0.8.20", ] [[package]] @@ -1837,9 +1837,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.18" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" +checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index a07e5607ae3..a854fa2a09e 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.11" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.18", features = ["derive"] } +zerocopy = { version = "0.8.20", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index c40e060677f..206d3884bfa 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.29", features = ["derive"] } +clap = { version = "4.5.31", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.93", features = ["span-locations"] } quote = "1.0.38" @@ -18,7 +18,7 @@ syn = { version = "2.0.98", features = ["full", "extra-traits", "visit", "visit- walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.13.1", features = ["v4"] } +uuid = { version = "1.14.0", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 0eb8da92d29..d3266a49e4d 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,12 +10,12 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.29", features = ["derive", "string"] } +clap = { version = "4.5.31", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.138" +serde = { version = "1.0.218", features = ["derive"] } +serde_json = "1.0.139" thiserror = "2.0.11" vmm = { path = "../vmm" } diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 43ecc1e9dbe..254725da377 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,13 +18,13 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -serde = { version = "1.0.217", features = ["derive"] } +serde = { version = "1.0.218", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.138" +serde_json = "1.0.139" thiserror = "2.0.11" timerfd = "1.6.0" utils = { path = "../utils" } @@ -33,17 +33,17 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] cargo_toml = "0.21.0" -libc = "0.2.169" +libc = "0.2.170" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.217", features = ["derive"] } +serde = { version = "1.0.218", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.217" } -serde_json = "1.0.138" +serde = { version = "1.0.218" } +serde_json = "1.0.139" [features] tracing = ["log-instrument", "utils/tracing", "vmm/tracing"] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index be231386020..02cf94c4b3d 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,7 +12,7 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } thiserror = "2.0.11" diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index ef5ffde6d7d..1e7941b1b04 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -28,7 +28,7 @@ name = "five" name = "six" [dependencies] -log = "0.4.25" +log = "0.4.26" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index f52933ddaae..3edd60dd30e 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } thiserror = "2.0.11" vmm-sys-util = "0.12.1" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index f69f55b84ac..2ce444191cf 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,13 +17,13 @@ bench = false [dependencies] bincode = "1.2.1" -clap = { version = "4.5.29", features = ["derive", "string"] } +clap = { version = "4.5.31", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.169" -serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.138" +libc = "0.2.170" +serde = { version = "1.0.218", features = ["derive"] } +serde_json = "1.0.139" thiserror = "2.0.11" -zerocopy = { version = "0.8.18" } +zerocopy = { version = "0.8.20" } [lints] workspace = true diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 0019afda741..b418c73e734 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,11 +10,11 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.29", features = ["derive", "string"] } +clap = { version = "4.5.31", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } semver = "1.0.25" thiserror = "2.0.11" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index d8b13452089..0648cedb8fc 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -10,7 +10,7 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.169" +libc = "0.2.170" log-instrument = { path = "../log-instrument", optional = true } thiserror = "2.0.11" diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 035e28505a3..f1464a0a585 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.12.2", features = ["bindgen"] } +aws-lc-rs = { version = "1.12.4", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" bitflags = "2.8.0" @@ -24,16 +24,16 @@ gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.11.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.20.0" -libc = "0.2.169" +libc = "0.2.170" linux-loader = "0.13.0" -log = { version = "0.4.25", features = ["std", "serde"] } +log = { version = "0.4.26", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } semver = { version = "1.0.25", features = ["serde"] } -serde = { version = "1.0.217", features = ["derive", "rc"] } -serde_json = "1.0.138" +serde = { version = "1.0.218", features = ["derive", "rc"] } +serde_json = "1.0.139" slab = "0.4.7" thiserror = "2.0.11" timerfd = "1.5.0" @@ -44,7 +44,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.18" } +zerocopy = { version = "0.8.20" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 57ea620f914ffb067e79137cd6b51895f74d4933 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Feb 2025 11:20:00 +0000 Subject: [PATCH 245/464] Reduce amount of data downloaded from GitHub in resources/rebuild.sh Use a tree-less git checkout [1], which reduces the amount of data downloaded by ~60% (from >3GiB to ~1GiB currently) when cloneing the upstream amazon linux repository from GitHub. It will now download some stuff during checkout, but this is significantly less than a full clone, as we're only checking out a handful of tags. We sadly cannot use a `--depth=1` checkout because we need access to all tags, in chronological order, and for this, we need at least the commit metadata itself fetched locally (even git ls-remote --tags will not sort tags without first fetching these). [1]: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/ Signed-off-by: Patrick Roy --- resources/rebuild.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 90bac7addb7..56afd1bdbac 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -120,7 +120,7 @@ EOF } function clone_amazon_linux_repo { - [ -d linux ] || git clone https://github.com/amazonlinux/linux linux + [ -d linux ] || git clone --no-checkout --filter=tree:0 https://github.com/amazonlinux/linux } # prints the git tag corresponding to the newest and best matching the provided kernel version $1 @@ -145,7 +145,8 @@ function build_al_kernel { local KERNEL_VERSION=$(echo $KERNEL_CFG | grep -Po "microvm-kernel-ci-$ARCH-\K(\d+\.\d+)") pushd linux - make distclean + # fails immediately after clone because nothing is checked out + make distclean || true git checkout $(get_tag $KERNEL_VERSION) From 9ff2c7b574d6e889895ee05841ba54ebc7aa43f1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Feb 2025 12:40:46 +0000 Subject: [PATCH 246/464] fix: Add keyboard drivers to CI guest kernels Firecracker supports sending a CTRL+ALT+DEL event to the guest, to trigger a reboot, and we had an integration test for this. However, the integration test was broken (see #5050), and actually, our guest kernels dont have the necessary drivers compiled in to actually receive the CTRL+ALT+DEL. Fix this by actually enabling the relavant Kconfigs. We don't re-build the artifacts just yet, as it'll happen anyway in a few days when we branch off the next release. Suggested-by: Riccardo Mancini Signed-off-by: Patrick Roy --- resources/guest_configs/ci.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config index 7bbf1fb1f56..166ab94db3f 100644 --- a/resources/guest_configs/ci.config +++ b/resources/guest_configs/ci.config @@ -5,3 +5,10 @@ CONFIG_SQUASHFS_ZSTD=y # aarch64 only TBD split into a separate file CONFIG_DEVMEM=y # CONFIG_ARM64_ERRATUM_3194386 is not set +# Needed for CTRL+ALT+DEL support +CONFIG_SERIO=y +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 From ecad2fd70c4d7f0364ecf1145ae85bde21f6ba72 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 26 Feb 2025 17:00:16 +0000 Subject: [PATCH 247/464] feat: add support got Graviton 4 cpu detection First step to test m8g is to identify if you run on m8g. Signed-off-by: Egor Lazarchuk --- tests/framework/utils_cpuid.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py index dabfb220240..979f4478c8b 100644 --- a/tests/framework/utils_cpuid.py +++ b/tests/framework/utils_cpuid.py @@ -28,6 +28,7 @@ class CpuModel(str, Enum): AMD_GENOA = "AMD_GENOA" 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" @@ -41,7 +42,11 @@ class CpuModel(str, Enum): "Intel(R) Xeon(R) Platinum 8375C CPU": "INTEL_ICELAKE", }, CpuVendor.AMD: {"AMD EPYC 7R13": "AMD_MILAN", "AMD EPYC 9R14": "AMD_GENOA"}, - CpuVendor.ARM: {"0xd0c": "ARM_NEOVERSE_N1", "0xd40": "ARM_NEOVERSE_V1"}, + CpuVendor.ARM: { + "0xd0c": "ARM_NEOVERSE_N1", + "0xd40": "ARM_NEOVERSE_V1", + "0xd4f": "ARM_NEOVERSE_V2", + }, } From 32ebbbec8146fe1f76b25251a827af9ed84ff01d Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 26 Feb 2025 14:40:57 +0000 Subject: [PATCH 248/464] feat: add Graviton 4 guest cpu features Add new set of guest features specific for graviton 4. Signed-off-by: Egor Lazarchuk --- .../integration_tests/functional/test_cpu_features_aarch64.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 2068194a894..5b667d0b34d 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -24,6 +24,8 @@ G3_SVE_AND_PAC = set("paca pacg sve svebf16 svei8mm".split()) +G4_FEATS = (G3_FEATS | set("bti flagm2 frint sb".split())) - set("sm3 sm4".split()) + def test_guest_cpu_features(uvm_any): """Check the CPU features for a microvm with different CPU templates""" @@ -43,6 +45,8 @@ def test_guest_cpu_features(uvm_any): expected_cpu_features = G3_FEATS | G3_SVE_AND_PAC case CpuModel.ARM_NEOVERSE_V1, None: expected_cpu_features = G3_FEATS + case CpuModel.ARM_NEOVERSE_V2, None: + expected_cpu_features = G4_FEATS guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) assert guest_feats == expected_cpu_features From dd0bf861ca43f99375b1eb76b275bbc5e45085b1 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 26 Feb 2025 16:53:55 +0000 Subject: [PATCH 249/464] feat: add Graviton 4 host vs guest cpu difference Add additional Graviton 4 cpu features to the host vs guest test. Signed-off-by: Egor Lazarchuk --- .../functional/test_cpu_features_host_vs_guest.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 d2fd4936328..c8075faa505 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 @@ -257,12 +257,21 @@ def test_host_vs_guest_cpu_features(uvm_nano): assert host_feats - guest_feats == expected_host_minus_guest assert guest_feats - host_feats == expected_guest_minus_host - case CpuModel.ARM_NEOVERSE_V1: + case CpuModel.ARM_NEOVERSE_V1 | CpuModel.ARM_NEOVERSE_V2: expected_guest_minus_host = set() # KVM does not enable PAC or SVE features by default # and Firecracker does not enable them either. expected_host_minus_guest = {"paca", "pacg", "sve", "svebf16", "svei8mm"} + if CPU_MODEL == CpuModel.ARM_NEOVERSE_V2: + expected_host_minus_guest |= { + "svebitperm", + "svesha3", + "sveaes", + "sve2", + "svepmull", + } + # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since # they have an errata whereby an MSR to the SSBS special-purpose register does not # affect subsequent speculative instructions, permitting speculative store bypassing for From 34337a6221acd8437bd1f944c4cd1f8d3dc15874 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 11:37:16 +0000 Subject: [PATCH 250/464] fix formatting in fast_page_fault_helper.c Add spaces before parenthesis Suggested-by: Babis Chalios Signed-off-by: Patrick Roy --- resources/overlay/usr/local/bin/fast_page_fault_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index d304b97f94d..36a20cc37b7 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -20,18 +20,19 @@ int main(int argc, char *const argv[]) { sigset_t set; int signal; + void *ptr; sigemptyset(&set); - if(sigaddset(&set, SIGUSR1) == -1) { + if (sigaddset(&set, SIGUSR1) == -1) { perror("sigaddset"); return -1; } - void *ptr = mmap(NULL, MEM_SIZE_MIB, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + ptr = mmap(NULL, MEM_SIZE_MIB, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); memset(ptr, 1, MEM_SIZE_MIB); - if(MAP_FAILED == ptr) { + if (MAP_FAILED == ptr) { perror("mmap"); return -1; } From 44b4c1bb9aa6d5f79304286a7dee0a1247d363af Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 11:38:16 +0000 Subject: [PATCH 251/464] fix(test): check for mmap errors before using pointer mmap should never fail, but having the check for failure after the memset is just wrong. Signed-off-by: Patrick Roy --- resources/overlay/usr/local/bin/fast_page_fault_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index 36a20cc37b7..a1f443f2f12 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -30,13 +30,13 @@ int main(int argc, char *const argv[]) { ptr = mmap(NULL, MEM_SIZE_MIB, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - memset(ptr, 1, MEM_SIZE_MIB); - if (MAP_FAILED == ptr) { perror("mmap"); return -1; } + memset(ptr, 1, MEM_SIZE_MIB); + sigwait(&set, &signal); memset(ptr, 2, MEM_SIZE_MIB); From 06172864750d00da097af25e2f85b88a66a004be Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 11:39:55 +0000 Subject: [PATCH 252/464] fast_page_fault_helper: return 1 instead of -1 in case of error -1 wraps around to 255, which in case of commands executed over SSH clashes with SSH defined return codes. Signed-off-by: Patrick Roy --- resources/overlay/usr/local/bin/fast_page_fault_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index a1f443f2f12..63739bc3c0e 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -25,14 +25,14 @@ int main(int argc, char *const argv[]) { sigemptyset(&set); if (sigaddset(&set, SIGUSR1) == -1) { perror("sigaddset"); - return -1; + return 1; } ptr = mmap(NULL, MEM_SIZE_MIB, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (MAP_FAILED == ptr) { perror("mmap"); - return -1; + return 1; } memset(ptr, 1, MEM_SIZE_MIB); From 51167e62fa0bf22526c0be8d66964e5ec647c801 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 11:40:58 +0000 Subject: [PATCH 253/464] fix(test): install signal mask in fast_page_fault_helper Without calling sigprocmask, the SIGUSR1 that we're using will actually just kill the process instead of waking it up, as sigwait can only be used to wait for _pending_ signals, but signals are only marked as pending if they're blocked by a signal mask. If they're not blocked, they will instead call signal handlers, which will in this case just kill the process. This does mean that this program never worked the intended way, which also kinda proves it was not needed to show the different in page faults between huge pages and normal pages (test_ept_violation_count). Signed-off-by: Patrick Roy --- resources/overlay/usr/local/bin/fast_page_fault_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index 63739bc3c0e..591ac3b9612 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -27,6 +27,10 @@ int main(int argc, char *const argv[]) { perror("sigaddset"); return 1; } + if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { + perror("sigprocmask"); + return 1; + } ptr = mmap(NULL, MEM_SIZE_MIB, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); From 7e909888a06336b4509c110a5fb388959ddb00bf Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 12:19:49 +0000 Subject: [PATCH 254/464] refactor(test): introduce utils_uffd.py Currently, all tests that want to make use of UFFD import UFFD related functions from test_uffd.py. That's a bit awkward, so move them into their own utility module. Signed-off-by: Patrick Roy --- tests/framework/utils.py | 64 ------------- tests/framework/utils_uffd.py | 92 +++++++++++++++++++ .../integration_tests/functional/test_uffd.py | 21 +---- .../performance/test_huge_pages.py | 2 +- 4 files changed, 95 insertions(+), 84 deletions(-) create mode 100644 tests/framework/utils_uffd.py diff --git a/tests/framework/utils.py b/tests/framework/utils.py index e89b8706651..093667f5743 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -10,7 +10,6 @@ import re import select import signal -import stat import subprocess import time import typing @@ -133,69 +132,6 @@ def chroot(path): os.chdir(working_dir) -class UffdHandler: - """Describe the UFFD page fault handler process.""" - - def __init__(self, name, socket_path, mem_file, chroot_path, log_file_name): - """Instantiate the handler process with arguments.""" - self._proc = None - self._handler_name = name - self._socket_path = socket_path - self._mem_file = mem_file - self._chroot = chroot_path - self._log_file = log_file_name - - def spawn(self, uid, gid): - """Spawn handler process using arguments provided.""" - - with chroot(self._chroot): - st = os.stat(self._handler_name) - os.chmod(self._handler_name, st.st_mode | stat.S_IEXEC) - - chroot_log_file = Path("/") / self._log_file - with open(chroot_log_file, "w", encoding="utf-8") as logfile: - args = [f"/{self._handler_name}", self._socket_path, self._mem_file] - self._proc = subprocess.Popen( - args, stdout=logfile, stderr=subprocess.STDOUT - ) - - # Give it time start and fail, if it really has too (bad things happen). - time.sleep(1) - if not self.is_running(): - print(chroot_log_file.read_text(encoding="utf-8")) - assert False, "Could not start PF handler!" - - # The page fault handler will create the socket path with root rights. - # Change rights to the jailer's. - os.chown(self._socket_path, uid, gid) - - @property - def proc(self): - """Return UFFD handler process.""" - return self._proc - - def is_running(self): - """Check if UFFD process is running""" - return self.proc is not None and self.proc.poll() is None - - @property - def log_file(self): - """Return the path to the UFFD handler's log file""" - return Path(self._chroot) / Path(self._log_file) - - @property - def log_data(self): - """Return the log data of the UFFD handler""" - if self.log_file is None: - return "" - return self.log_file.read_text(encoding="utf-8") - - def __del__(self): - """Tear down the UFFD handler process.""" - if self.proc is not None: - self.proc.kill() - - class CpuMap: """Cpu map from real cpu cores to containers visible cores. diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py new file mode 100644 index 00000000000..09c231559e2 --- /dev/null +++ b/tests/framework/utils_uffd.py @@ -0,0 +1,92 @@ +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""UFFD related utility functions""" + +import os +import stat +import subprocess +import time +from pathlib import Path + +from framework.utils import chroot + +SOCKET_PATH = "/firecracker-uffd.sock" + + +class UffdHandler: + """Describe the UFFD page fault handler process.""" + + def __init__(self, name, socket_path, mem_file, chroot_path, log_file_name): + """Instantiate the handler process with arguments.""" + self._proc = None + self._handler_name = name + self._socket_path = socket_path + self._mem_file = mem_file + self._chroot = chroot_path + self._log_file = log_file_name + + def spawn(self, uid, gid): + """Spawn handler process using arguments provided.""" + + with chroot(self._chroot): + st = os.stat(self._handler_name) + os.chmod(self._handler_name, st.st_mode | stat.S_IEXEC) + + chroot_log_file = Path("/") / self._log_file + with open(chroot_log_file, "w", encoding="utf-8") as logfile: + args = [f"/{self._handler_name}", self._socket_path, self._mem_file] + self._proc = subprocess.Popen( + args, stdout=logfile, stderr=subprocess.STDOUT + ) + + # Give it time start and fail, if it really has too (bad things happen). + time.sleep(1) + if not self.is_running(): + print(chroot_log_file.read_text(encoding="utf-8")) + assert False, "Could not start PF handler!" + + # The page fault handler will create the socket path with root rights. + # Change rights to the jailer's. + os.chown(self._socket_path, uid, gid) + + @property + def proc(self): + """Return UFFD handler process.""" + return self._proc + + def is_running(self): + """Check if UFFD process is running""" + return self.proc is not None and self.proc.poll() is None + + @property + def log_file(self): + """Return the path to the UFFD handler's log file""" + return Path(self._chroot) / Path(self._log_file) + + @property + def log_data(self): + """Return the log data of the UFFD handler""" + if self.log_file is None: + return "" + return self.log_file.read_text(encoding="utf-8") + + def __del__(self): + """Tear down the UFFD handler process.""" + if self.proc is not None: + self.proc.kill() + + +def spawn_pf_handler(vm, handler_path, mem_path): + """Spawn page fault handler process.""" + # Copy snapshot memory file into chroot of microVM. + jailed_mem = vm.create_jailed_resource(mem_path) + # Copy the valid page fault binary into chroot of microVM. + jailed_handler = vm.create_jailed_resource(handler_path) + handler_name = os.path.basename(jailed_handler) + + uffd_handler = UffdHandler( + handler_name, SOCKET_PATH, jailed_mem, vm.chroot(), "uffd.log" + ) + uffd_handler.spawn(vm.jailer.uid, vm.jailer.gid) + + return uffd_handler diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index 398529de77d..a122abbc066 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -8,9 +8,8 @@ import pytest import requests -from framework.utils import Timeout, UffdHandler, check_output - -SOCKET_PATH = "/firecracker-uffd.sock" +from framework.utils import Timeout, check_output +from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler @pytest.fixture(scope="function", name="snapshot") @@ -36,22 +35,6 @@ def snapshot_fxt(microvm_factory, guest_kernel_linux_5_10, rootfs): yield snapshot -def spawn_pf_handler(vm, handler_path, mem_path): - """Spawn page fault handler process.""" - # Copy snapshot memory file into chroot of microVM. - jailed_mem = vm.create_jailed_resource(mem_path) - # Copy the valid page fault binary into chroot of microVM. - jailed_handler = vm.create_jailed_resource(handler_path) - handler_name = os.path.basename(jailed_handler) - - uffd_handler = UffdHandler( - handler_name, SOCKET_PATH, jailed_mem, vm.chroot(), "uffd.log" - ) - uffd_handler.spawn(vm.jailer.uid, vm.jailer.gid) - - return uffd_handler - - def test_bad_socket_path(uvm_plain, snapshot): """ Test error scenario when socket path does not exist. diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 51b5dd57418..8f525aaed73 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -10,7 +10,7 @@ from framework.microvm import HugePagesConfig from framework.properties import global_props from framework.utils_ftrace import ftrace_events -from integration_tests.functional.test_uffd import SOCKET_PATH, spawn_pf_handler +from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler def check_hugetlbfs_in_use(pid: int, allocation_name: str): From a8f38cb521a73673d61e04310c2a5c5c89a7ee04 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 12:23:46 +0000 Subject: [PATCH 255/464] refactor(test): make uffd_handle_paths not be a fixture There's really no use in having this be a fixture, it's just a dictionary - it used to be a fixture because we were building the binaries inside of the test framework (and so each call to it as a function would trigger compilations), but now that we pre-compile everything that's no longer something to worry about. Signed-off-by: Patrick Roy --- tests/conftest.py | 10 --------- tests/framework/utils_uffd.py | 6 ++++++ .../integration_tests/functional/test_uffd.py | 14 +++++-------- .../performance/test_huge_pages.py | 21 ++++++------------- 4 files changed, 17 insertions(+), 34 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e3aea3a8dfa..fa309427ef1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -252,16 +252,6 @@ def bin_seccomp_paths(): yield demos -@pytest.fixture -def uffd_handler_paths(): - """Build UFFD handler binaries.""" - handlers = { - f"{handler}_handler": build_tools.get_example(f"uffd_{handler}_handler") - for handler in ["malicious", "valid", "fault_all"] - } - yield handlers - - @pytest.fixture(scope="session") def netns_factory(worker_id): """A network namespace factory diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py index 09c231559e2..9de89809a20 100644 --- a/tests/framework/utils_uffd.py +++ b/tests/framework/utils_uffd.py @@ -9,6 +9,7 @@ from pathlib import Path from framework.utils import chroot +from host_tools import cargo_build SOCKET_PATH = "/firecracker-uffd.sock" @@ -90,3 +91,8 @@ def spawn_pf_handler(vm, handler_path, mem_path): uffd_handler.spawn(vm.jailer.uid, vm.jailer.gid) return uffd_handler + + +def uffd_handler(handler_name): + """Retrieves the uffd handler with the given name""" + return cargo_build.get_example(f"uffd_{handler_name}_handler") diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index a122abbc066..cb5ac0c44c9 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -9,7 +9,7 @@ import requests from framework.utils import Timeout, check_output -from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler +from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler, uffd_handler @pytest.fixture(scope="function", name="snapshot") @@ -83,7 +83,7 @@ def test_unbinded_socket(uvm_plain, snapshot): vm.mark_killed() -def test_valid_handler(uvm_plain, snapshot, uffd_handler_paths): +def test_valid_handler(uvm_plain, snapshot): """ Test valid uffd handler scenario. """ @@ -92,9 +92,7 @@ def test_valid_handler(uvm_plain, snapshot, uffd_handler_paths): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler( - vm, uffd_handler_paths["valid_handler"], snapshot.mem - ) + _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) @@ -111,7 +109,7 @@ def test_valid_handler(uvm_plain, snapshot, uffd_handler_paths): vm.ssh.check_output("true") -def test_malicious_handler(uvm_plain, snapshot, uffd_handler_paths): +def test_malicious_handler(uvm_plain, snapshot): """ Test malicious uffd handler scenario. @@ -127,9 +125,7 @@ def test_malicious_handler(uvm_plain, snapshot, uffd_handler_paths): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler( - vm, uffd_handler_paths["malicious_handler"], snapshot.mem - ) + _pf_handler = spawn_pf_handler(vm, uffd_handler("malicious"), snapshot.mem) # We expect Firecracker to freeze while resuming from a snapshot # due to the malicious handler's unavailability. diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 8f525aaed73..65ae2e6fbc2 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -10,7 +10,7 @@ from framework.microvm import HugePagesConfig from framework.properties import global_props from framework.utils_ftrace import ftrace_events -from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler +from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler, uffd_handler def check_hugetlbfs_in_use(pid: int, allocation_name: str): @@ -69,9 +69,7 @@ def test_hugetlbfs_boot(uvm_plain): ) -def test_hugetlbfs_snapshot( - microvm_factory, guest_kernel_linux_5_10, rootfs, uffd_handler_paths -): +def test_hugetlbfs_snapshot(microvm_factory, guest_kernel_linux_5_10, rootfs): """ Test hugetlbfs snapshot restore via uffd """ @@ -95,16 +93,14 @@ def test_hugetlbfs_snapshot( vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler( - vm, uffd_handler_paths["valid_handler"], snapshot.mem - ) + _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) check_hugetlbfs_in_use(vm.firecracker_pid, "/anon_hugepage") -def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths): +def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain): """ Test hugetlbfs differential snapshot support. @@ -139,9 +135,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain, uffd_handler_paths) vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler( - vm, uffd_handler_paths["valid_handler"], snapshot_merged.mem - ) + _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot_merged.mem) vm.restore_from_snapshot(snapshot_merged, resume=True, uffd_path=SOCKET_PATH) @@ -153,7 +147,6 @@ def test_ept_violation_count( microvm_factory, guest_kernel_linux_5_10, rootfs, - uffd_handler_paths, metrics, huge_pages, ): @@ -200,9 +193,7 @@ def test_ept_violation_count( vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler( - vm, uffd_handler_paths["fault_all_handler"], snapshot.mem - ) + _pf_handler = spawn_pf_handler(vm, uffd_handler("fault_all"), snapshot.mem) with ftrace_events("kvm:*"): vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) From 0ec23adbcbdf49dc7133691a3c110ffdf4bd5186 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Fri, 28 Feb 2025 12:35:43 +0000 Subject: [PATCH 256/464] fix: do not build debug a default seccomp policy in debug binaries Rust 1.80.0 added a debug assertion that uses fcntl(F_GETFD) to ensure the fd is still valid when it gets dropped, which broke debug builds of firecracker. This made us rethink on whether we'd want any default seccomp policy in debug builds, and we decided that in most cases we don't need them and in some cases they get in the way of prororyping and debugging. This patch changes the default seccomp policy in debug builds to empty. Signed-off-by: Riccardo Mancini --- src/firecracker/build.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/firecracker/build.rs b/src/firecracker/build.rs index 87710b54fc4..595b1e0c00a 100644 --- a/src/firecracker/build.rs +++ b/src/firecracker/build.rs @@ -14,23 +14,34 @@ const SECCOMPILER_SRC_DIR: &str = "../seccompiler/src"; fn main() { // Target triple let target = std::env::var("TARGET").expect("Missing target."); + let debug: bool = std::env::var("DEBUG") + .expect("Missing debug.") + .parse() + .expect("Invalid env variable DEBUG"); let out_dir = std::env::var("OUT_DIR").expect("Missing build-level OUT_DIR."); // Target arch (x86_64 / aarch64) let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").expect("Missing target arch."); let seccomp_json_path = format!("{}/{}.json", JSON_DIR, target); - // If the current target doesn't have a default filter, use a default, empty filter. + // If the current target doesn't have a default filter, or if we're building a debug binary, + // use a default, empty filter. // This is to make sure that Firecracker builds even with libc toolchains for which we don't // provide a default filter. For example, GNU libc. - let seccomp_json_path = if Path::new(&seccomp_json_path).exists() { - seccomp_json_path - } else { + let seccomp_json_path = if debug { + println!( + "cargo:warning=Using empty default seccomp policy for debug builds: \ + `resources/seccomp/unimplemented.json`." + ); + format!("{}/unimplemented.json", JSON_DIR) + } else if !Path::new(&seccomp_json_path).exists() { println!( "cargo:warning=No default seccomp policy for target: {}. Defaulting to \ `resources/seccomp/unimplemented.json`.", target ); format!("{}/unimplemented.json", JSON_DIR) + } else { + seccomp_json_path }; // Retrigger the build script if the JSON file has changed. From 5890dbe8e2ba47b58150724d4cca891c240a567f Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Fri, 28 Feb 2025 13:34:39 +0000 Subject: [PATCH 257/464] doc(seccomp): mention that debug builds don't have a default seccomp Following the previous commit, this patch mentions in the docs that debug builds don't have a default seccomp policy and which different syscalls are present in debug builds versus release. Signed-off-by: Riccardo Mancini --- docs/seccomp.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/seccomp.md b/docs/seccomp.md index dac55006bc5..06c7fd92d76 100644 --- a/docs/seccomp.md +++ b/docs/seccomp.md @@ -11,8 +11,10 @@ follows: - API - right before launching the HTTP server; - VCPUs - right before executing guest code. -**Note**: On experimental GNU targets, there are no default seccomp filters -installed, since they are not intended for production use. +> [!WARNING] +> +> On debug binaries and experimental GNU targets, there are no default seccomp +> filters installed, since they are not intended for production use. Firecracker uses JSON files for expressing the filter rules and relies on the [seccompiler](seccompiler.md) tool for all the seccomp functionality. @@ -58,6 +60,12 @@ Potential use cases: - Users of experimentally-supported targets (like GNU libc builds) may be able to use this feature to implement seccomp filters without needing to have a custom build of Firecracker. +- Users of debug binaries who need to use a seccomp filter for any reason will + be able to use this feature to implement seccomp filters without needing to + have a custom build of Firecracker. Note: there may be some differences in + syscalls between `debug` and `release` builds. A non-comprehensive list is: + - `fcntl(F_GETFD)` is used by debug assertions to verify a dropped `fd` is + valid. - Faced with a _theoretical_ production issue, due to a syscall that was issued by the Firecracker process, but not allowed by the seccomp policy, one may use a custom filter in order to quickly mitigate the issue. This can speed up the From fe54515923554453c7e8f473a8911e39c333f903 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 3 Mar 2025 10:49:38 +0000 Subject: [PATCH 258/464] doc(changelog): add note about empty seccomp policy in debug builds This patch adds an entry to the "Fixed" changelog list mentioning that debug builds are now built with an empty default seccomp policy. Signed-off-by: Riccardo Mancini --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 673a1b7a88d..7c4ed83f012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,9 @@ and this project adheres to - [#5046](https://github.com/firecracker-microvm/firecracker/pull/5046): Retry KVM_CREATE_VM on EINTR that occasionally happen on heavily loaded hosts to improve reliability of microVM creation. +- [#5052](https://github.com/firecracker-microvm/firecracker/pull/5052): Build + the empty seccomp policy as default for debug builds to avoid crashes on + syscalls introduced by debug assertions from Rust 1.80.0. ## [1.10.1] From c54ecd7709e63b1a036945d3f345eb69f457dca2 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 3 Mar 2025 15:23:30 +0000 Subject: [PATCH 259/464] chore: update CHANGELOG in preparation of 1.11 release Mark all unreleased changes as 1.11, add new empty unreleased section. Signed-off-by: Riccardo Mancini --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c4ed83f012..64034de9932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,18 @@ and this project adheres to ### Added +### Changed + +### Deprecated + +### Removed + +### Fixed + +## [1.11.0] + +### Added + - [#4987](https://github.com/firecracker-microvm/firecracker/pull/4987): Reset physical counter register (`CNTPCT_EL0`) on VM startup. This avoids VM reading the host physical counter value. This is only possible on 6.4 and newer From b4cb9d311d026c5e45f13bd56089d2db024ec983 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 3 Mar 2025 17:40:55 +0000 Subject: [PATCH 260/464] chore: bump version to 1.12.0-dev Generated running `./tools/bump-version.sh 1.12.0-dev` Signed-off-by: Riccardo Mancini --- Cargo.lock | 12 ++++++------ src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 2 +- src/firecracker/swagger/firecracker.yaml | 2 +- src/jailer/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a667da093cc..6774369a2b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,7 +411,7 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "cpu-template-helper" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "clap", "displaydoc", @@ -599,7 +599,7 @@ dependencies = [ [[package]] name = "firecracker" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "cargo_toml", "displaydoc", @@ -804,7 +804,7 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jailer" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "libc", "log-instrument", @@ -1149,7 +1149,7 @@ dependencies = [ [[package]] name = "rebase-snap" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "displaydoc", "libc", @@ -1224,7 +1224,7 @@ dependencies = [ [[package]] name = "seccompiler" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "bincode", "clap", @@ -1303,7 +1303,7 @@ dependencies = [ [[package]] name = "snapshot-editor" -version = "1.11.0-dev" +version = "1.12.0-dev" dependencies = [ "clap", "clap-num", diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index d3266a49e4d..2a9e7f61efd 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpu-template-helper" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 254725da377..29778af061d 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "firecracker" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" build = "build.rs" diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index 20bad48bf64..de6d1e3da40 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -5,7 +5,7 @@ info: The API is accessible through HTTP calls on specific URLs carrying JSON modeled data. The transport medium is a Unix Domain Socket. - version: 1.11.0-dev + version: 1.12.0-dev termsOfService: "" contact: email: "compute-capsule@amazon.com" diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 02cf94c4b3d..d3965c5070f 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jailer" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" description = "Process for starting Firecracker in production scenarios; applies a cgroup/namespace isolation barrier and then drops privileges." diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index 3edd60dd30e..b2d1dc4a90c 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rebase-snap" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 2ce444191cf..d88d2722d51 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "seccompiler" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" description = "Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file." diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index b418c73e734..9d95dd721db 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snapshot-editor" -version = "1.11.0-dev" +version = "1.12.0-dev" authors = ["Amazon Firecracker team "] edition = "2021" license = "Apache-2.0" From 74a51618038dba82cfa8c4c19d281188aa25cbfc Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 5 Mar 2025 17:02:18 +0000 Subject: [PATCH 261/464] doc(vsock): clarify vsock support on snapshot/restore The current documentation is not clear, mentioning that the device could break if active at time of snapshot. It also mentions that this is fixed by resetting the device at snapshot time, closing all open connections. This patch clarifies that vsock connections are explicitly closed by a transport reset, in order to avoid the aforementioned issue. This doesn't impact listening sockets as they are able to accept new connections after restore. Signed-off-by: Riccardo Mancini --- docs/snapshotting/snapshot-support.md | 39 +++++++++++---------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index e1294e1ac7d..dc4235b6aad 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -57,7 +57,10 @@ creation process). Both network and vsock packet loss can be expected on guests that are resumed from snapshots in another Firecracker process. It is also not guaranteed that -the state of the network connections survives the process. +the state of the network connections survives the process. Furthermore, vsock +connections that are open when the snapshot is taken are closed, but existing +vsock listen sockets in the guest still remain active and can accept new +connections after resume (see [Vsock device reset](#vsock-device-reset)). In order to make restoring possible, Firecracker snapshots save the full state of the following resources: @@ -141,8 +144,6 @@ The snapshot functionality is still in developer preview due to the following: - Guest network connectivity is not guaranteed to be preserved after resume. For recommendations related to guest network connectivity for clones please see [Network connectivity for clones](network-for-clones.md). -- Vsock device does not have full snapshotting support. Please see - [Vsock device limitation](#vsock-device-limitation). - Snapshotting on arm64 works for both GICv2 and GICv3 enabled guests. However, restoring between different GIC version is not possible. - If a [CPU template](../cpu_templates/cpu-templates.md) is not used on x86_64, @@ -606,29 +607,19 @@ identifiers, cached random numbers, cryptographic tokens, etc **will** still be replicated across multiple microVMs resumed from the same snapshot. Users need to implement mechanisms for ensuring de-duplication of such state, where needed. -## Vsock device limitation +## Vsock device reset -Vsock must be inactive during snapshot. Vsock device can break if snapshotted -while having active connections. Firecracker snapshots do not capture any -inflight network or vsock (through the linux unix domain socket backend) traffic -that has left or not yet entered Firecracker. - -The above, coupled with the fact that Vsock control protocol is not resilient to -vsock packet loss, leads to Vsock device breakage when doing a snapshot while -there are active Vsock connections. - -As a solution to the above issue, active Vsock connections prior to snapshotting -the VM are forcibly closed by sending a specific event called -`VIRTIO_VSOCK_EVENT_TRANSPORT_RESET`. The event is sent on `SnapshotCreate`. On +The vsock device is reset across snapshot/restore to avoid inconsistent state +between device and driver leading to breakage +([#2218](https://github.com/firecracker-microvm/firecracker/issues/2218)). This +is done by sending a `VIRTIO_VSOCK_EVENT_TRANSPORT_RESET` event to the guest +driver during `SnapshotCreate` +([#2562](https://github.com/firecracker-microvm/firecracker/pull/2562)). On `SnapshotResume`, when the VM becomes active again, the vsock driver closes all -existing connections. Listen sockets still remain active. Users wanting to build -vsock applications that use the snapshot capability have to take this into -consideration. More details about this event can be found in the official Virtio -document [here](https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf), -section 5.10.6.6 Device Events. - -Firecracker handles sending the `reset` event to the vsock driver, thus the -customers are no longer responsible for closing active connections. +existing connections. Existing listen sockets still remain active, but their CID +is updated to reflect the current `guest_cid`. More details about this event can +be found in the official Virtio document +[here](https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-4080006). ## VMGenID device limitation From 6a0072806dbf7e5d0b3f811851531555ca54c5fc Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 5 Mar 2025 17:40:13 +0000 Subject: [PATCH 262/464] chore(jailer): clarify main function wrapping Add a comment why we wrap the actual main inplementation. Signed-off-by: Egor Lazarchuk --- src/jailer/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs index fc7ac216599..f5ebd663b02 100644 --- a/src/jailer/src/main.rs +++ b/src/jailer/src/main.rs @@ -305,6 +305,7 @@ pub fn to_cstring + Debug>(path: T) -> Result Result<(), JailerError> { let result = main_exec(); if let Err(e) = result { From 020e343d7747a72c883e3f609dd08fbd707861ca Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 5 Mar 2025 17:45:58 +0000 Subject: [PATCH 263/464] refactor(jailer): use C-string literals Since Rust 1.77 we can create constants with C strings without runtime conversion. Signed-off-by: Egor Lazarchuk --- src/jailer/src/chroot.rs | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/jailer/src/chroot.rs b/src/jailer/src/chroot.rs index 44386729196..cad575227f4 100644 --- a/src/jailer/src/chroot.rs +++ b/src/jailer/src/chroot.rs @@ -10,9 +10,9 @@ use vmm_sys_util::syscall::SyscallReturnCode; use super::{to_cstring, JailerError}; -const OLD_ROOT_DIR_NAME_NUL_TERMINATED: &[u8] = b"old_root\0"; -const ROOT_DIR_NUL_TERMINATED: &[u8] = b"/\0"; -const CURRENT_DIR_NUL_TERMINATED: &[u8] = b".\0"; +const OLD_ROOT_DIR: &CStr = c"old_root"; +const ROOT_DIR: &CStr = c"/"; +const CURRENT_DIR: &CStr = c"."; // This uses switching to a new mount namespace + pivot_root(), together with the regular chroot, // to provide a hardened jail (at least compared to only relying on chroot). @@ -24,16 +24,13 @@ pub fn chroot(path: &Path) -> Result<(), JailerError> { .into_empty_result() .map_err(JailerError::UnshareNewNs)?; - let root_dir = CStr::from_bytes_with_nul(ROOT_DIR_NUL_TERMINATED) - .map_err(JailerError::FromBytesWithNul)?; - // Recursively change the propagation type of all the mounts in this namespace to SLAVE, so // we can call pivot_root. // SAFETY: Safe because we provide valid parameters. SyscallReturnCode(unsafe { libc::mount( null(), - root_dir.as_ptr(), + ROOT_DIR.as_ptr(), null(), libc::MS_SLAVE | libc::MS_REC, null(), @@ -64,25 +61,21 @@ pub fn chroot(path: &Path) -> Result<(), JailerError> { // Change current dir to the chroot dir, so we only need to handle relative paths from now on. env::set_current_dir(path).map_err(JailerError::SetCurrentDir)?; - // We use the CStr conversion to make sure the contents of the byte slice would be a - // valid C string (and for the as_ptr() method). - let old_root_dir = CStr::from_bytes_with_nul(OLD_ROOT_DIR_NAME_NUL_TERMINATED) - .map_err(JailerError::FromBytesWithNul)?; - // Create the old_root folder we're going to use for pivot_root, using a relative path. // SAFETY: The call is safe because we provide valid arguments. - SyscallReturnCode(unsafe { libc::mkdir(old_root_dir.as_ptr(), libc::S_IRUSR | libc::S_IWUSR) }) + SyscallReturnCode(unsafe { libc::mkdir(OLD_ROOT_DIR.as_ptr(), libc::S_IRUSR | libc::S_IWUSR) }) .into_empty_result() .map_err(JailerError::MkdirOldRoot)?; - let cwd = CStr::from_bytes_with_nul(CURRENT_DIR_NUL_TERMINATED) - .map_err(JailerError::FromBytesWithNul)?; - // We are now ready to call pivot_root. We have to use sys_call because there is no libc // wrapper for pivot_root. // SAFETY: Safe because we provide valid parameters. SyscallReturnCode(unsafe { - libc::syscall(libc::SYS_pivot_root, cwd.as_ptr(), old_root_dir.as_ptr()) + libc::syscall( + libc::SYS_pivot_root, + CURRENT_DIR.as_ptr(), + OLD_ROOT_DIR.as_ptr(), + ) }) .into_empty_result() .map_err(JailerError::PivotRoot)?; @@ -90,19 +83,19 @@ pub fn chroot(path: &Path) -> Result<(), JailerError> { // pivot_root doesn't guarantee that we will be in "/" at this point, so switch to "/" // explicitly. // SAFETY: Safe because we provide valid parameters. - SyscallReturnCode(unsafe { libc::chdir(root_dir.as_ptr()) }) + SyscallReturnCode(unsafe { libc::chdir(ROOT_DIR.as_ptr()) }) .into_empty_result() .map_err(JailerError::ChdirNewRoot)?; // Umount the old_root, thus isolating the process from everything outside the jail root folder. // SAFETY: Safe because we provide valid parameters. - SyscallReturnCode(unsafe { libc::umount2(old_root_dir.as_ptr(), libc::MNT_DETACH) }) + SyscallReturnCode(unsafe { libc::umount2(OLD_ROOT_DIR.as_ptr(), libc::MNT_DETACH) }) .into_empty_result() .map_err(JailerError::UmountOldRoot)?; // Remove the no longer necessary old_root directory. // SAFETY: Safe because we provide valid parameters. - SyscallReturnCode(unsafe { libc::rmdir(old_root_dir.as_ptr()) }) + SyscallReturnCode(unsafe { libc::rmdir(OLD_ROOT_DIR.as_ptr()) }) .into_empty_result() .map_err(JailerError::RmOldRootDir) } From 8411b07c97555e4e60115eee86c5910b75e68f32 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 5 Mar 2025 18:02:12 +0000 Subject: [PATCH 264/464] refactor(jailer): use CStr for strings As a follow up of the previous commit, replace string which should be C string with CStr. Signed-off-by: Egor Lazarchuk --- src/jailer/src/env.rs | 45 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index 61cd121b0dc..d2e9a80711a 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -1,7 +1,7 @@ // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use std::ffi::{CString, OsString}; +use std::ffi::{CStr, CString, OsString}; use std::fs::{self, canonicalize, read_to_string, File, OpenOptions, Permissions}; use std::io; use std::io::Write; @@ -30,19 +30,19 @@ const STDERR_FILENO: libc::c_int = 2; // Kernel-based virtual machine (hardware virtualization extensions) // minor/major numbers are taken from // https://www.kernel.org/doc/html/latest/admin-guide/devices.html -const DEV_KVM_WITH_NUL: &str = "/dev/kvm"; +const DEV_KVM: &CStr = c"/dev/kvm"; const DEV_KVM_MAJOR: u32 = 10; const DEV_KVM_MINOR: u32 = 232; // TUN/TAP device minor/major numbers are taken from // www.kernel.org/doc/Documentation/networking/tuntap.txt -const DEV_NET_TUN_WITH_NUL: &str = "/dev/net/tun"; +const DEV_NET_TUN: &CStr = c"/dev/net/tun"; const DEV_NET_TUN_MAJOR: u32 = 10; const DEV_NET_TUN_MINOR: u32 = 200; // Random number generator device minor/major numbers are taken from // https://www.kernel.org/doc/Documentation/admin-guide/devices.txt -const DEV_URANDOM_WITH_NUL: &str = "/dev/urandom"; +const DEV_URANDOM: &CStr = c"/dev/urandom"; const DEV_URANDOM_MAJOR: u32 = 1; const DEV_URANDOM_MINOR: u32 = 9; @@ -54,7 +54,7 @@ const DEV_URANDOM_MINOR: u32 = 9; // so we will have to find it at initialization time parsing /proc/misc. // What we do know is the major number for misc devices: // https://elixir.bootlin.com/linux/v6.1.51/source/Documentation/admin-guide/devices.txt -const DEV_UFFD_PATH: &str = "/dev/userfaultfd"; +const DEV_UFFD_PATH: &CStr = c"/dev/userfaultfd"; const DEV_UFFD_MAJOR: u32 = 10; // Relevant folders inside the jail that we create or/and for which we change ownership. @@ -425,18 +425,17 @@ impl Env { fn mknod_and_own_dev( &self, - dev_path_str: &'static str, + dev_path: &CStr, dev_major: u32, dev_minor: u32, ) -> Result<(), JailerError> { - let dev_path = CString::new(dev_path_str).unwrap(); // As per sysstat.h: // S_IFCHR -> character special device // S_IRUSR -> read permission, owner // S_IWUSR -> write permission, owner // See www.kernel.org/doc/Documentation/networking/tuntap.txt, 'Configuration' chapter for // more clarity. - // SAFETY: This is safe because dev_path is CString, and hence null-terminated. + // SAFETY: This is safe because dev_path is CStr, and hence null-terminated. SyscallReturnCode(unsafe { libc::mknod( dev_path.as_ptr(), @@ -445,7 +444,7 @@ impl Env { ) }) .into_empty_result() - .map_err(|err| JailerError::MknodDev(err, dev_path_str.to_owned()))?; + .map_err(|err| JailerError::MknodDev(err, dev_path.to_str().unwrap().to_owned()))?; // SAFETY: This is safe because dev_path is CStr, and hence null-terminated. SyscallReturnCode(unsafe { libc::chown(dev_path.as_ptr(), self.uid(), self.gid()) }) @@ -663,14 +662,14 @@ impl Env { // $: mknod $dev_net_tun_path c 10 200 // www.kernel.org/doc/Documentation/networking/tuntap.txt specifies 10 and 200 as the major // and minor for the /dev/net/tun device. - self.mknod_and_own_dev(DEV_NET_TUN_WITH_NUL, DEV_NET_TUN_MAJOR, DEV_NET_TUN_MINOR)?; + self.mknod_and_own_dev(DEV_NET_TUN, DEV_NET_TUN_MAJOR, DEV_NET_TUN_MINOR)?; // Do the same for /dev/kvm with (major, minor) = (10, 232). - self.mknod_and_own_dev(DEV_KVM_WITH_NUL, DEV_KVM_MAJOR, DEV_KVM_MINOR)?; + self.mknod_and_own_dev(DEV_KVM, DEV_KVM_MAJOR, DEV_KVM_MINOR)?; // And for /dev/urandom with (major, minor) = (1, 9). // If the device is not accessible on the host, output a warning to inform user that MMDS // version 2 will not be available to use. let _ = self - .mknod_and_own_dev(DEV_URANDOM_WITH_NUL, DEV_URANDOM_MAJOR, DEV_URANDOM_MINOR) + .mknod_and_own_dev(DEV_URANDOM, DEV_URANDOM_MAJOR, DEV_URANDOM_MINOR) .map_err(|err| { println!( "Warning! Could not create /dev/urandom device inside jailer: {}.", @@ -1116,14 +1115,14 @@ mod tests { // process management; it can't be isolated from side effects. } - fn ensure_mknod_and_own_dev(env: &Env, dev_path: &'static str, major: u32, minor: u32) { + fn ensure_mknod_and_own_dev(env: &Env, dev_path: &CStr, major: u32, minor: u32) { use std::os::unix::fs::FileTypeExt; // Create a new device node. env.mknod_and_own_dev(dev_path, major, minor).unwrap(); // Ensure device's properties. - let metadata = fs::metadata(dev_path).unwrap(); + let metadata = fs::metadata(dev_path.to_str().unwrap()).unwrap(); assert!(metadata.file_type().is_char_device()); assert_eq!(get_major(metadata.st_rdev()), major); assert_eq!(get_minor(metadata.st_rdev()), minor); @@ -1140,7 +1139,7 @@ mod tests { ), format!( "Failed to create {} via mknod inside the jail: File exists (os error 17)", - dev_path + dev_path.to_str().unwrap() ) ); } @@ -1152,25 +1151,25 @@ mod tests { let env = create_env(mock_cgroups.proc_mounts_path.as_str()); // Ensure device nodes are created with correct major/minor numbers and permissions. - let mut dev_infos: Vec<(&str, u32, u32)> = vec![ - ("/dev/net/tun-test", DEV_NET_TUN_MAJOR, DEV_NET_TUN_MINOR), - ("/dev/kvm-test", DEV_KVM_MAJOR, DEV_KVM_MINOR), + let mut dev_infos: Vec<(&CStr, u32, u32)> = vec![ + (c"/dev/net/tun-test", DEV_NET_TUN_MAJOR, DEV_NET_TUN_MINOR), + (c"/dev/kvm-test", DEV_KVM_MAJOR, DEV_KVM_MINOR), ]; if let Some(uffd_dev_minor) = env.uffd_dev_minor { - dev_infos.push(("/dev/userfaultfd-test", DEV_UFFD_MAJOR, uffd_dev_minor)); + dev_infos.push((c"/dev/userfaultfd-test", DEV_UFFD_MAJOR, uffd_dev_minor)); } for (dev, major, minor) in dev_infos { // Checking this just to be super sure there's no file at `dev_str` path (though // it shouldn't be as we deleted it at the end of the previous test run). - if Path::new(dev).exists() { - fs::remove_file(dev).unwrap(); + if Path::new(dev.to_str().unwrap()).exists() { + fs::remove_file(dev.to_str().unwrap()).unwrap(); } ensure_mknod_and_own_dev(&env, dev, major, minor); // Remove the device node. - fs::remove_file(dev).expect("Could not remove file."); + fs::remove_file(dev.to_str().unwrap()).expect("Could not remove file."); } } @@ -1180,7 +1179,7 @@ mod tests { mock_cgroups.add_v1_mounts().unwrap(); let env = create_env(mock_cgroups.proc_mounts_path.as_str()); - if !Path::new(DEV_UFFD_PATH).exists() { + if !Path::new(DEV_UFFD_PATH.to_str().unwrap()).exists() { assert_eq!(env.uffd_dev_minor, None); } else { assert!(env.uffd_dev_minor.is_some()); From 473b07be3782831c139baf218055a4ea3642c047 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Sun, 2 Oct 2022 10:42:24 -0700 Subject: [PATCH 265/464] pvh/arch: Introduce EntryPoint struct In order to properly configure the initial vCPU register state and boot parameters in guest memory, we must specify which boot protocol to use with the kernel entry point address. On x86-64 (the only architecture where multiple boot protocols are supported) we print the protocol used to load the kernel at the debug log level. Create an EntryPoint struct that contains the required information. This structure will later be used in the vCPU configuration methods to set the appropriate initial conditions for the guest. This commit also splits the load_kernel function into an x86-64 specific version and an aarch64 specific version. Signed-off-by: Colin Percival Co-authored-by: Alejandro Jimenez Signed-off-by: Patrick Roy --- src/vmm/src/arch/mod.rs | 32 ++++++++++++++++++ src/vmm/src/builder.rs | 53 +++++++++++++++++++++++++----- src/vmm/src/vstate/vcpu/aarch64.rs | 1 + 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index a51055622e4..8fa7c2463bf 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -6,6 +6,7 @@ use std::sync::LazyLock; use log::warn; use serde::{Deserialize, Serialize}; +use vm_memory::GuestAddress; /// Module for aarch64 related functionality. #[cfg(target_arch = "aarch64")] @@ -77,3 +78,34 @@ impl fmt::Display for DeviceType { write!(f, "{:?}", self) } } + +/// Suported boot protocols for +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum BootProtocol { + /// Linux 64-bit boot protocol + LinuxBoot, + #[cfg(target_arch = "x86_64")] + /// PVH boot protocol (x86/HVM direct boot ABI) + PvhBoot, +} + +impl fmt::Display for BootProtocol { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"), + #[cfg(target_arch = "x86_64")] + BootProtocol::PvhBoot => write!(f, "PVH boot protocol"), + } + } +} + +#[derive(Debug, Copy, Clone)] +/// Specifies the entry point address where the guest must start +/// executing code, as well as which boot protocol is to be used +/// to configure the guest initial state. +pub struct EntryPoint { + /// Address in guest memory where the guest must start execution + pub entry_addr: GuestAddress, + /// Specifies which boot protocol to use + pub protocol: BootProtocol, +} diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 3f6847aa8dc..a73322a7ffb 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -16,6 +16,8 @@ use libc::EFD_NONBLOCK; use linux_loader::cmdline::Cmdline as LoaderKernelCmdline; #[cfg(target_arch = "x86_64")] use linux_loader::loader::elf::Elf as Loader; +#[cfg(target_arch = "x86_64")] +use linux_loader::loader::elf::PvhBootCapability; #[cfg(target_arch = "aarch64")] use linux_loader::loader::pe::PE as Loader; use linux_loader::loader::KernelLoader; @@ -29,7 +31,7 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] use crate::acpi; -use crate::arch::InitrdConfig; +use crate::arch::{BootProtocol, EntryPoint, InitrdConfig}; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; use crate::cpu_config::templates::{ @@ -256,7 +258,7 @@ pub fn build_microvm_for_boot( .allocate_guest_memory() .map_err(StartMicrovmError::GuestMemory)?; - let entry_addr = load_kernel(boot_config, &guest_memory)?; + let entry_point = load_kernel(boot_config, &guest_memory)?; let initrd = load_initrd_from_config(boot_config, &guest_memory)?; // Clone the command-line so that a failed boot doesn't pollute the original. #[allow(unused_mut)] @@ -330,7 +332,7 @@ pub fn build_microvm_for_boot( vcpus.as_mut(), &vm_resources.machine_config, &cpu_template, - entry_addr, + entry_point.entry_addr, &initrd, boot_cmdline, )?; @@ -339,8 +341,14 @@ pub fn build_microvm_for_boot( #[cfg(feature = "gdb")] if let Some(gdb_socket_path) = &vm_resources.machine_config.gdb_socket_path { - gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_path) - .map_err(GdbServer)?; + gdb::gdb_thread( + vmm.clone(), + vcpu_fds, + gdb_rx, + entry_point.entry_addr, + gdb_socket_path, + ) + .map_err(GdbServer)?; } else { debug!("No GDB socket provided not starting gdb server."); } @@ -562,13 +570,12 @@ pub fn build_microvm_from_snapshot( fn load_kernel( boot_config: &BootConfig, guest_memory: &GuestMemoryMmap, -) -> Result { +) -> Result { let mut kernel_file = boot_config .kernel_file .try_clone() .map_err(|err| StartMicrovmError::Internal(VmmError::KernelFile(err)))?; - #[cfg(target_arch = "x86_64")] let entry_addr = Loader::load::( guest_memory, None, @@ -577,7 +584,32 @@ fn load_kernel( ) .map_err(StartMicrovmError::KernelLoader)?; - #[cfg(target_arch = "aarch64")] + let mut entry_point_addr: GuestAddress = entry_addr.kernel_load; + let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot; + if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap { + // Use the PVH kernel entry point to boot the guest + entry_point_addr = pvh_entry_addr; + boot_prot = BootProtocol::PvhBoot; + } + + debug!("Kernel loaded using {boot_prot}"); + + Ok(EntryPoint { + entry_addr: entry_point_addr, + protocol: boot_prot, + }) +} + +#[cfg(target_arch = "aarch64")] +fn load_kernel( + boot_config: &BootConfig, + guest_memory: &GuestMemoryMmap, +) -> Result { + let mut kernel_file = boot_config + .kernel_file + .try_clone() + .map_err(|err| StartMicrovmError::Internal(VmmError::KernelFile(err)))?; + let entry_addr = Loader::load::( guest_memory, Some(GuestAddress(crate::arch::get_kernel_start())), @@ -586,7 +618,10 @@ fn load_kernel( ) .map_err(StartMicrovmError::KernelLoader)?; - Ok(entry_addr.kernel_load) + Ok(EntryPoint { + entry_addr: entry_addr.kernel_load, + protocol: BootProtocol::LinuxBoot, + }) } fn load_initrd_from_config( diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index 7bdde9b9d1f..e7de8d8abcc 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -302,6 +302,7 @@ mod tests { use std::os::unix::io::AsRawFd; use kvm_bindings::{KVM_ARM_VCPU_PSCI_0_2, KVM_REG_SIZE_U64}; + use vm_memory::GuestAddress; use super::*; use crate::arch::aarch64::regs::Aarch64RegisterRef; From bb38ffac21c59a9cc97236b3d95878075d0f25d9 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Sun, 2 Oct 2022 10:42:38 -0700 Subject: [PATCH 266/464] pvh/arch-x86_64: Initialize vCPU regs for PVH Set the initial values of the KVM vCPU registers as specified in the PVH boot ABI: https://xenbits.xen.org/docs/unstable/misc/pvh.html Add stub bits for aarch64; PVH mode does not exist there. Signed-off-by: Colin Percival Co-authored-by: Alejandro Jimenez --- src/vmm/src/arch/x86_64/gdt.rs | 36 +++++- src/vmm/src/arch/x86_64/layout.rs | 3 + src/vmm/src/arch/x86_64/regs.rs | 174 +++++++++++++++++++++-------- src/vmm/src/builder.rs | 9 +- src/vmm/src/vstate/vcpu/aarch64.rs | 22 +++- src/vmm/src/vstate/vcpu/mod.rs | 10 +- src/vmm/src/vstate/vcpu/x86_64.rs | 52 +++++++-- 7 files changed, 232 insertions(+), 74 deletions(-) diff --git a/src/vmm/src/arch/x86_64/gdt.rs b/src/vmm/src/arch/x86_64/gdt.rs index 41f2b0f8340..b7b99a572ae 100644 --- a/src/vmm/src/arch/x86_64/gdt.rs +++ b/src/vmm/src/arch/x86_64/gdt.rs @@ -1,3 +1,5 @@ +// Copyright © 2020, Oracle and/or its affiliates. +// // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // @@ -24,8 +26,38 @@ fn get_base(entry: u64) -> u64 { | (((entry) & 0x0000_0000_FFFF_0000) >> 16) } +// Extract the segment limit from the GDT segment descriptor. +// +// In a segment descriptor, the limit field is 20 bits, so it can directly describe +// a range from 0 to 0xFFFFF (1 MB). When G flag is set (4-KByte page granularity) it +// scales the value in the limit field by a factor of 2^12 (4 Kbytes), making the effective +// limit range from 0xFFF (4 KBytes) to 0xFFFF_FFFF (4 GBytes). +// +// However, the limit field in the VMCS definition is a 32 bit field, and the limit value is not +// automatically scaled using the G flag. This means that for a desired range of 4GB for a +// given segment, its limit must be specified as 0xFFFF_FFFF. Therefore the method of obtaining +// the limit from the GDT entry is not sufficient, since it only provides 20 bits when 32 bits +// are necessary. Fortunately, we can check if the G flag is set when extracting the limit since +// the full GDT entry is passed as an argument, and perform the scaling of the limit value to +// return the full 32 bit value. +// +// The scaling mentioned above is required when using PVH boot, since the guest boots in protected +// (32-bit) mode and must be able to access the entire 32-bit address space. It does not cause +// issues for the case of direct boot to 64-bit (long) mode, since in 64-bit mode the processor does +// not perform runtime limit checking on code or data segments. +// +// (For more information concerning the formats of segment descriptors, VMCS fields, et cetera, +// please consult the Intel Software Developer Manual.) fn get_limit(entry: u64) -> u32 { - ((((entry) & 0x000F_0000_0000_0000) >> 32) as u32) | (((entry) & 0x0000_0000_0000_FFFF) as u32) + #[allow(clippy::cast_possible_truncation)] // clearly, truncation is not possible + let limit: u32 = + ((((entry) & 0x000F_0000_0000_0000) >> 32) | ((entry) & 0x0000_0000_0000_FFFF)) as u32; + + // Perform manual limit scaling if G flag is set + match get_g(entry) { + 0 => limit, + _ => (limit << 12) | 0xFFF, // G flag is either 0 or 1 + } } fn get_g(entry: u64) -> u8 { @@ -109,7 +141,7 @@ mod tests { assert_eq!(0xB, seg.type_); // base and limit assert_eq!(0x10_0000, seg.base); - assert_eq!(0xfffff, seg.limit); + assert_eq!(0xffff_ffff, seg.limit); assert_eq!(0x0, seg.unusable); } } diff --git a/src/vmm/src/arch/x86_64/layout.rs b/src/vmm/src/arch/x86_64/layout.rs index 1e50bb9c235..d3b4e3b5e9b 100644 --- a/src/vmm/src/arch/x86_64/layout.rs +++ b/src/vmm/src/arch/x86_64/layout.rs @@ -27,6 +27,9 @@ pub const IRQ_MAX: u32 = 23; /// Address for the TSS setup. pub const KVM_TSS_ADDRESS: u64 = 0xfffb_d000; +/// Address of the hvm_start_info struct used in PVH boot +pub const PVH_INFO_START: u64 = 0x6000; + /// The 'zero page', a.k.a linux kernel bootparams. pub const ZERO_PAGE_START: u64 = 0x7000; diff --git a/src/vmm/src/arch/x86_64/regs.rs b/src/vmm/src/arch/x86_64/regs.rs index aec47677c4c..0a4cf630bf3 100644 --- a/src/vmm/src/arch/x86_64/regs.rs +++ b/src/vmm/src/arch/x86_64/regs.rs @@ -1,3 +1,4 @@ +// Copyright © 2020, Oracle and/or its affiliates. // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // @@ -10,6 +11,7 @@ use std::mem; use kvm_bindings::{kvm_fpu, kvm_regs, kvm_sregs}; use kvm_ioctls::VcpuFd; +use super::super::{BootProtocol, EntryPoint}; use super::gdt::{gdt_entry, kvm_segment_from_gdt}; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; @@ -80,20 +82,30 @@ pub struct SetupRegistersError(vmm_sys_util::errno::Error); /// # Errors /// /// When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_regs`] errors. -pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<(), SetupRegistersError> { - let regs: kvm_regs = kvm_regs { - rflags: 0x0000_0000_0000_0002u64, - rip: boot_ip, - // Frame pointer. It gets a snapshot of the stack pointer (rsp) so that when adjustments are - // made to rsp (i.e. reserving space for local variables or pushing values on to the stack), - // local variables and function parameters are still accessible from a constant offset from - // rbp. - rsp: super::layout::BOOT_STACK_POINTER, - // Starting stack pointer. - rbp: super::layout::BOOT_STACK_POINTER, - // Must point to zero page address per Linux ABI. This is x86_64 specific. - rsi: super::layout::ZERO_PAGE_START, - ..Default::default() +pub fn setup_regs(vcpu: &VcpuFd, entry_point: EntryPoint) -> Result<(), SetupRegistersError> { + let regs: kvm_regs = match entry_point.protocol { + BootProtocol::PvhBoot => kvm_regs { + // Configure regs as required by PVH boot protocol. + rflags: 0x0000_0000_0000_0002u64, + rbx: super::layout::PVH_INFO_START, + rip: entry_point.entry_addr.raw_value(), + ..Default::default() + }, + BootProtocol::LinuxBoot => kvm_regs { + // Configure regs as required by Linux 64-bit boot protocol. + rflags: 0x0000_0000_0000_0002u64, + rip: entry_point.entry_addr.raw_value(), + // Frame pointer. It gets a snapshot of the stack pointer (rsp) so that when adjustments + // are made to rsp (i.e. reserving space for local variables or pushing + // values on to the stack), local variables and function parameters are + // still accessible from a constant offset from rbp. + rsp: super::layout::BOOT_STACK_POINTER, + // Starting stack pointer. + rbp: super::layout::BOOT_STACK_POINTER, + // Must point to zero page address per Linux ABI. This is x86_64 specific. + rsi: super::layout::ZERO_PAGE_START, + ..Default::default() + }, }; vcpu.set_regs(®s).map_err(SetupRegistersError) @@ -118,6 +130,7 @@ pub enum SetupSpecialRegistersError { /// /// * `mem` - The memory that will be passed to the guest. /// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. +/// * `boot_prot` - The boot protocol being used. /// /// # Errors /// @@ -126,14 +139,21 @@ pub enum SetupSpecialRegistersError { /// - [`configure_segments_and_sregs`] errors. /// - [`setup_page_tables`] errors /// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_sregs`] errors. -pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &VcpuFd) -> Result<(), SetupSpecialRegistersError> { +pub fn setup_sregs( + mem: &GuestMemoryMmap, + vcpu: &VcpuFd, + boot_prot: BootProtocol, +) -> Result<(), SetupSpecialRegistersError> { let mut sregs: kvm_sregs = vcpu .get_sregs() .map_err(SetupSpecialRegistersError::GetSpecialRegisters)?; - configure_segments_and_sregs(mem, &mut sregs) + configure_segments_and_sregs(mem, &mut sregs, boot_prot) .map_err(SetupSpecialRegistersError::ConfigureSegmentsAndSpecialRegisters)?; - setup_page_tables(mem, &mut sregs).map_err(SetupSpecialRegistersError::SetupPageTables)?; // TODO(dgreid) - Can this be done once per system instead? + if let BootProtocol::LinuxBoot = boot_prot { + setup_page_tables(mem, &mut sregs).map_err(SetupSpecialRegistersError::SetupPageTables)?; + // TODO(dgreid) - Can this be done once per system instead? + } vcpu.set_sregs(&sregs) .map_err(SetupSpecialRegistersError::SetSpecialRegisters) @@ -148,6 +168,7 @@ const EFER_LMA: u64 = 0x400; const EFER_LME: u64 = 0x100; const X86_CR0_PE: u64 = 0x1; +const X86_CR0_ET: u64 = 0x10; const X86_CR0_PG: u64 = 0x8000_0000; const X86_CR4_PAE: u64 = 0x20; @@ -174,13 +195,28 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<(), RegsErro fn configure_segments_and_sregs( mem: &GuestMemoryMmap, sregs: &mut kvm_sregs, + boot_prot: BootProtocol, ) -> Result<(), RegsError> { - let gdt_table: [u64; BOOT_GDT_MAX] = [ - gdt_entry(0, 0, 0), // NULL - gdt_entry(0xa09b, 0, 0xfffff), // CODE - gdt_entry(0xc093, 0, 0xfffff), // DATA - gdt_entry(0x808b, 0, 0xfffff), // TSS - ]; + let gdt_table: [u64; BOOT_GDT_MAX] = match boot_prot { + BootProtocol::PvhBoot => { + // Configure GDT entries as specified by PVH boot protocol + [ + gdt_entry(0, 0, 0), // NULL + gdt_entry(0xc09b, 0, 0xffff_ffff), // CODE + gdt_entry(0xc093, 0, 0xffff_ffff), // DATA + gdt_entry(0x008b, 0, 0x67), // TSS + ] + } + BootProtocol::LinuxBoot => { + // Configure GDT entries as specified by Linux 64bit boot protocol + [ + gdt_entry(0, 0, 0), // NULL + gdt_entry(0xa09b, 0, 0xfffff), // CODE + gdt_entry(0xc093, 0, 0xfffff), // DATA + gdt_entry(0x808b, 0, 0xfffff), // TSS + ] + } + }; let code_seg = kvm_segment_from_gdt(gdt_table[1], 1); let data_seg = kvm_segment_from_gdt(gdt_table[2], 2); @@ -203,9 +239,17 @@ fn configure_segments_and_sregs( sregs.ss = data_seg; sregs.tr = tss_seg; - // 64-bit protected mode - sregs.cr0 |= X86_CR0_PE; - sregs.efer |= EFER_LME | EFER_LMA; + match boot_prot { + BootProtocol::PvhBoot => { + sregs.cr0 = X86_CR0_PE | X86_CR0_ET; + sregs.cr4 = 0; + } + BootProtocol::LinuxBoot => { + // 64-bit protected mode + sregs.cr0 |= X86_CR0_PE; + sregs.efer |= EFER_LME | EFER_LMA; + } + } Ok(()) } @@ -251,24 +295,45 @@ mod tests { gm.read_obj(read_addr).unwrap() } - fn validate_segments_and_sregs(gm: &GuestMemoryMmap, sregs: &kvm_sregs) { + fn validate_segments_and_sregs( + gm: &GuestMemoryMmap, + sregs: &kvm_sregs, + boot_prot: BootProtocol, + ) { + if let BootProtocol::LinuxBoot = boot_prot { + assert_eq!(0xaf_9b00_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 8)); + assert_eq!(0xcf_9300_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 16)); + assert_eq!(0x8f_8b00_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 24)); + + assert_eq!(0xffff_ffff, sregs.tr.limit); + + assert!(sregs.cr0 & X86_CR0_PE != 0); + assert!(sregs.efer & EFER_LME != 0 && sregs.efer & EFER_LMA != 0); + } else { + // Validate values that are specific to PVH boot protocol + assert_eq!(0xcf_9b00_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 8)); + assert_eq!(0xcf_9300_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 16)); + assert_eq!(0x00_8b00_0000_0067, read_u64(gm, BOOT_GDT_OFFSET + 24)); + + assert_eq!(0x67, sregs.tr.limit); + assert_eq!(0, sregs.tr.g); + + assert!(sregs.cr0 & X86_CR0_PE != 0 && sregs.cr0 & X86_CR0_ET != 0); + assert_eq!(0, sregs.cr4); + } + + // Common settings for both PVH and Linux boot protocol assert_eq!(0x0, read_u64(gm, BOOT_GDT_OFFSET)); - assert_eq!(0xaf_9b00_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 8)); - assert_eq!(0xcf_9300_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 16)); - assert_eq!(0x8f_8b00_0000_ffff, read_u64(gm, BOOT_GDT_OFFSET + 24)); assert_eq!(0x0, read_u64(gm, BOOT_IDT_OFFSET)); assert_eq!(0, sregs.cs.base); - assert_eq!(0xfffff, sregs.ds.limit); + assert_eq!(0xffff_ffff, sregs.ds.limit); assert_eq!(0x10, sregs.es.selector); assert_eq!(1, sregs.fs.present); assert_eq!(1, sregs.gs.g); assert_eq!(0, sregs.ss.avl); assert_eq!(0, sregs.tr.base); - assert_eq!(0xfffff, sregs.tr.limit); assert_eq!(0, sregs.tr.avl); - assert!(sregs.cr0 & X86_CR0_PE != 0); - assert!(sregs.efer & EFER_LME != 0 && sregs.efer & EFER_LMA != 0); } fn validate_page_tables(gm: &GuestMemoryMmap, sregs: &kvm_sregs) { @@ -320,7 +385,12 @@ mod tests { ..Default::default() }; - setup_regs(&vcpu, expected_regs.rip).unwrap(); + let entry_point: EntryPoint = EntryPoint { + entry_addr: GuestAddress(expected_regs.rip), + protocol: BootProtocol::LinuxBoot, + }; + + setup_regs(&vcpu, entry_point).unwrap(); let actual_regs: kvm_regs = vcpu.get_regs().unwrap(); assert_eq!(actual_regs, expected_regs); @@ -333,16 +403,22 @@ mod tests { let vcpu = vm.create_vcpu(0).unwrap(); let gm = single_region_mem(0x10000); - vcpu.set_sregs(&Default::default()).unwrap(); - setup_sregs(&gm, &vcpu).unwrap(); - - let mut sregs: kvm_sregs = vcpu.get_sregs().unwrap(); - // for AMD KVM_GET_SREGS returns g = 0 for each kvm_segment. - // We set it to 1, otherwise the test will fail. - sregs.gs.g = 1; - - validate_segments_and_sregs(&gm, &sregs); - validate_page_tables(&gm, &sregs); + [BootProtocol::LinuxBoot, BootProtocol::PvhBoot] + .iter() + .for_each(|boot_prot| { + vcpu.set_sregs(&Default::default()).unwrap(); + setup_sregs(&gm, &vcpu, *boot_prot).unwrap(); + + let mut sregs: kvm_sregs = vcpu.get_sregs().unwrap(); + // for AMD KVM_GET_SREGS returns g = 0 for each kvm_segment. + // We set it to 1, otherwise the test will fail. + sregs.gs.g = 1; + + validate_segments_and_sregs(&gm, &sregs, *boot_prot); + if let BootProtocol::LinuxBoot = *boot_prot { + validate_page_tables(&gm, &sregs); + } + }); } #[test] @@ -386,9 +462,13 @@ mod tests { fn test_configure_segments_and_sregs() { let mut sregs: kvm_sregs = Default::default(); let gm = single_region_mem(0x10000); - configure_segments_and_sregs(&gm, &mut sregs).unwrap(); + configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::LinuxBoot).unwrap(); + + validate_segments_and_sregs(&gm, &sregs, BootProtocol::LinuxBoot); + + configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::PvhBoot).unwrap(); - validate_segments_and_sregs(&gm, &sregs); + validate_segments_and_sregs(&gm, &sregs, BootProtocol::PvhBoot); } #[test] diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index a73322a7ffb..cbcae8c0dd9 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -332,7 +332,7 @@ pub fn build_microvm_for_boot( vcpus.as_mut(), &vm_resources.machine_config, &cpu_template, - entry_point.entry_addr, + entry_point, &initrd, boot_cmdline, )?; @@ -567,6 +567,7 @@ pub fn build_microvm_from_snapshot( Ok(vmm) } +#[cfg(target_arch = "x86_64")] fn load_kernel( boot_config: &BootConfig, guest_memory: &GuestMemoryMmap, @@ -751,7 +752,7 @@ pub fn configure_system_for_boot( vcpus: &mut [Vcpu], machine_config: &MachineConfig, cpu_template: &CustomCpuTemplate, - entry_addr: GuestAddress, + entry_point: EntryPoint, initrd: &Option, boot_cmdline: LoaderKernelCmdline, ) -> Result<(), StartMicrovmError> { @@ -802,7 +803,7 @@ pub fn configure_system_for_boot( // Configure vCPUs with normalizing and setting the generated CPU configuration. for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu - .configure(vmm.guest_memory(), entry_addr, &vcpu_config) + .configure(vmm.guest_memory(), entry_point, &vcpu_config) .map_err(VmmError::VcpuConfigure) .map_err(Internal)?; } @@ -847,7 +848,7 @@ pub fn configure_system_for_boot( vcpu.kvm_vcpu .configure( vmm.guest_memory(), - entry_addr, + entry_point, &vcpu_config, &optional_capabilities, ) diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index e7de8d8abcc..c5d3f4dbb8b 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -18,12 +18,13 @@ use crate::arch::aarch64::vcpu::{ get_all_registers, get_all_registers_ids, get_mpidr, get_mpstate, get_registers, set_mpstate, set_register, setup_boot_regs, VcpuError as ArchError, }; +use crate::arch::EntryPoint; use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; use crate::cpu_config::templates::CpuConfiguration; use crate::logger::{error, IncMetric, METRICS}; use crate::vcpu::{VcpuConfig, VcpuError}; use crate::vstate::kvm::OptionalCapabilities; -use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; +use crate::vstate::memory::{Address, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuEmulation; use crate::vstate::vm::Vm; @@ -109,12 +110,13 @@ impl KvmVcpu { /// # Arguments /// /// * `guest_mem` - The guest memory used by this microvm. - /// * `kernel_load_addr` - Offset from `guest_mem` at which the kernel is loaded. + /// * `kernel_entry_point` - Specifies the boot protocol and offset from `guest_mem` at which + /// the kernel starts. /// * `vcpu_config` - The vCPU configuration. pub fn configure( &mut self, guest_mem: &GuestMemoryMmap, - kernel_load_addr: GuestAddress, + kernel_entry_point: EntryPoint, vcpu_config: &VcpuConfig, optional_capabilities: &OptionalCapabilities, ) -> Result<(), KvmVcpuError> { @@ -127,7 +129,7 @@ impl KvmVcpu { setup_boot_regs( &self.fd, self.index, - kernel_load_addr.raw_value(), + kernel_entry_point.entry_addr.raw_value(), guest_mem, optional_capabilities, ) @@ -306,6 +308,7 @@ mod tests { use super::*; use crate::arch::aarch64::regs::Aarch64RegisterRef; + use crate::arch::BootProtocol; use crate::cpu_config::aarch64::CpuConfiguration; use crate::cpu_config::templates::RegisterValueFilter; use crate::vcpu::VcpuConfig; @@ -349,9 +352,13 @@ mod tests { smt: false, cpu_config: CpuConfiguration::default(), }; + vcpu.configure( &vm_mem, - GuestAddress(crate::arch::get_kernel_start()), + EntryPoint { + entry_addr: GuestAddress(crate::arch::get_kernel_start()), + protocol: BootProtocol::LinuxBoot, + }, &vcpu_config, &optional_capabilities, ) @@ -361,7 +368,10 @@ mod tests { let err = vcpu.configure( &vm_mem, - GuestAddress(crate::arch::get_kernel_start()), + EntryPoint { + entry_addr: GuestAddress(crate::arch::get_kernel_start()), + protocol: BootProtocol::LinuxBoot, + }, &vcpu_config, &optional_capabilities, ); diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index b120a9f2c07..047b40b133a 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -780,6 +780,7 @@ pub(crate) mod tests { use vmm_sys_util::errno; use super::*; + use crate::arch::{BootProtocol, EntryPoint}; use crate::builder::StartMicrovmError; use crate::devices::bus::DummyDevice; use crate::devices::BusDevice; @@ -978,7 +979,10 @@ pub(crate) mod tests { let vcpu_exit_evt = vcpu.exit_evt.try_clone().unwrap(); // Needs a kernel since we'll actually run this vcpu. - let entry_addr = load_good_kernel(&vm_mem); + let entry_point = EntryPoint { + entry_addr: load_good_kernel(&vm_mem), + protocol: BootProtocol::LinuxBoot, + }; #[cfg(target_arch = "x86_64")] { @@ -986,7 +990,7 @@ pub(crate) mod tests { vcpu.kvm_vcpu .configure( &vm_mem, - entry_addr, + entry_point, &VcpuConfig { vcpu_count: 1, smt: false, @@ -1003,7 +1007,7 @@ pub(crate) mod tests { vcpu.kvm_vcpu .configure( &vm_mem, - entry_addr, + entry_point, &VcpuConfig { vcpu_count: 1, smt: false, diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 85c2db3868f..7f223b4daa9 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -21,9 +21,10 @@ use crate::arch::x86_64::gen::msr_index::{MSR_IA32_TSC, MSR_IA32_TSC_DEADLINE}; use crate::arch::x86_64::interrupts; use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError}; use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError}; +use crate::arch::EntryPoint; use crate::cpu_config::x86_64::{cpuid, CpuConfiguration}; use crate::logger::{IncMetric, METRICS}; -use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap}; +use crate::vstate::memory::GuestMemoryMmap; use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation}; use crate::vstate::vm::Vm; @@ -183,13 +184,14 @@ impl KvmVcpu { /// # Arguments /// /// * `guest_mem` - The guest memory used by this microvm. - /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts. + /// * `kernel_entry_point` - Specifies the boot protocol and offset from `guest_mem` at which + /// the kernel starts. /// * `vcpu_config` - The vCPU configuration. /// * `cpuid` - The capabilities exposed by this vCPU. pub fn configure( &mut self, guest_mem: &GuestMemoryMmap, - kernel_start_addr: GuestAddress, + kernel_entry_point: EntryPoint, vcpu_config: &VcpuConfig, ) -> Result<(), KvmVcpuConfigureError> { let mut cpuid = vcpu_config.cpu_config.cpuid.clone(); @@ -249,11 +251,10 @@ impl KvmVcpu { .collect::>(); crate::arch::x86_64::msr::set_msrs(&self.fd, &kvm_msrs)?; - crate::arch::x86_64::regs::setup_regs(&self.fd, kernel_start_addr.raw_value())?; + crate::arch::x86_64::regs::setup_regs(&self.fd, kernel_entry_point)?; crate::arch::x86_64::regs::setup_fpu(&self.fd)?; - crate::arch::x86_64::regs::setup_sregs(guest_mem, &self.fd)?; + crate::arch::x86_64::regs::setup_sregs(guest_mem, &self.fd, kernel_entry_point.protocol)?; crate::arch::x86_64::interrupts::set_lint(&self.fd)?; - Ok(()) } @@ -717,9 +718,11 @@ mod tests { use kvm_bindings::kvm_msr_entry; use kvm_ioctls::Cap; + use vm_memory::GuestAddress; use super::*; use crate::arch::x86_64::cpu_model::CpuModel; + use crate::arch::BootProtocol; use crate::cpu_config::templates::{ CpuConfiguration, CpuTemplateType, CustomCpuTemplate, GetCpuTemplate, GuestConfigError, StaticCpuTemplate, @@ -790,7 +793,14 @@ mod tests { let vcpu_config = create_vcpu_config(&kvm, &vcpu, &CustomCpuTemplate::default()).unwrap(); assert_eq!( - vcpu.configure(&vm_mem, GuestAddress(0), &vcpu_config,), + vcpu.configure( + &vm_mem, + EntryPoint { + entry_addr: GuestAddress(0), + protocol: BootProtocol::LinuxBoot, + }, + &vcpu_config, + ), Ok(()) ); @@ -802,7 +812,10 @@ mod tests { Ok(config) => vcpu .configure( &vm_mem, - GuestAddress(crate::arch::get_kernel_start()), + EntryPoint { + entry_addr: GuestAddress(crate::arch::get_kernel_start()), + protocol: BootProtocol::LinuxBoot, + }, &config, ) .is_ok(), @@ -905,8 +918,15 @@ mod tests { msrs: BTreeMap::new(), }, }; - vcpu.configure(&vm_mem, GuestAddress(0), &vcpu_config) - .unwrap(); + vcpu.configure( + &vm_mem, + EntryPoint { + entry_addr: GuestAddress(0), + protocol: BootProtocol::LinuxBoot, + }, + &vcpu_config, + ) + .unwrap(); // Invalid entries filled with 0 should not exist. let cpuid = vcpu.get_cpuid().unwrap(); @@ -967,8 +987,16 @@ mod tests { msrs: BTreeMap::new(), }, }; - vcpu.configure(&vm_mem, GuestAddress(0), &vcpu_config) - .unwrap(); + + vcpu.configure( + &vm_mem, + EntryPoint { + entry_addr: GuestAddress(0), + protocol: BootProtocol::LinuxBoot, + }, + &vcpu_config, + ) + .unwrap(); vcpu.dump_cpu_config().unwrap(); } From 0553a6bcaa61402868c44977aa997d28fcff34c9 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Sun, 2 Oct 2022 10:42:41 -0700 Subject: [PATCH 267/464] pvh/arch-x86_64: Write start_info to guest memory Fill the hvm_start_info and related structures as specified in the PVH boot protocol. Write the data structures to guest memory at the GPA that will be stored in %rbx when the guest starts. Signed-off-by: Colin Percival Co-authored-by: Alejandro Jimenez Signed-off-by: Patrick Roy --- src/vmm/src/arch/x86_64/layout.rs | 8 ++ src/vmm/src/arch/x86_64/mod.rs | 186 +++++++++++++++++++++++++++++- src/vmm/src/builder.rs | 1 + 3 files changed, 189 insertions(+), 6 deletions(-) diff --git a/src/vmm/src/arch/x86_64/layout.rs b/src/vmm/src/arch/x86_64/layout.rs index d3b4e3b5e9b..18d718a49b8 100644 --- a/src/vmm/src/arch/x86_64/layout.rs +++ b/src/vmm/src/arch/x86_64/layout.rs @@ -30,6 +30,14 @@ pub const KVM_TSS_ADDRESS: u64 = 0xfffb_d000; /// Address of the hvm_start_info struct used in PVH boot pub const PVH_INFO_START: u64 = 0x6000; +/// Starting address of array of modules of hvm_modlist_entry type. +/// Used to enable initrd support using the PVH boot ABI. +pub const MODLIST_START: u64 = 0x6040; + +/// Address of memory map table used in PVH boot. Can overlap +/// with the zero page address since they are mutually exclusive. +pub const MEMMAP_START: u64 = 0x7000; + /// The 'zero page', a.k.a linux kernel bootparams. pub const ZERO_PAGE_START: u64 = 0x7000; diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 40f4f15607a..80030216fdb 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -1,3 +1,5 @@ +// Copyright © 2020, Oracle and/or its affiliates. +// // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // @@ -22,10 +24,14 @@ pub mod regs; pub mod gen; use linux_loader::configurator::linux::LinuxBootConfigurator; +use linux_loader::configurator::pvh::PvhBootConfigurator; use linux_loader::configurator::{BootConfigurator, BootParams}; use linux_loader::loader::bootparam::boot_params; +use linux_loader::loader::elf::start_info::{ + hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info, +}; -use crate::arch::InitrdConfig; +use crate::arch::{BootProtocol, InitrdConfig, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::device_manager::resources::ResourceAllocator; use crate::utils::u64_to_usize; use crate::vstate::memory::{ @@ -35,8 +41,10 @@ use crate::vstate::memory::{ // Value taken from https://elixir.bootlin.com/linux/v5.10.68/source/arch/x86/include/uapi/asm/e820.h#L31 // Usable normal RAM const E820_RAM: u32 = 1; + // Reserved area that should be avoided during memory allocations const E820_RESERVED: u32 = 2; +const MEMMAP_TYPE_RAM: u32 = 1; /// Errors thrown while configuring x86_64 system. #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] @@ -49,6 +57,12 @@ pub enum ConfigurationError { ZeroPageSetup, /// Failed to compute initrd address. InitrdAddress, + /// Error writing module entry to guest memory. + ModlistSetup, + /// Error writing memory map table to guest memory. + MemmapTableSetup, + /// Error writing hvm_start_info to guest memory. + StartInfoSetup, } const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32; @@ -110,6 +124,7 @@ pub fn initrd_load_addr( /// * `cmdline_size` - Size of the kernel command line in bytes including the null terminator. /// * `initrd` - Information about where the ramdisk image was loaded in the `guest_mem`. /// * `num_cpus` - Number of virtual CPUs the guest will have. +/// * `boot_prot` - Boot protocol that will be used to boot the guest. pub fn configure_system( guest_mem: &GuestMemoryMmap, resource_allocator: &mut ResourceAllocator, @@ -117,6 +132,128 @@ pub fn configure_system( cmdline_size: usize, initrd: &Option, num_cpus: u8, + boot_prot: BootProtocol, +) -> Result<(), ConfigurationError> { + // Note that this puts the mptable at the last 1k of Linux's 640k base RAM + mptable::setup_mptable(guest_mem, resource_allocator, num_cpus) + .map_err(ConfigurationError::MpTableSetup)?; + + match boot_prot { + BootProtocol::PvhBoot => { + configure_pvh(guest_mem, cmdline_addr, initrd)?; + } + BootProtocol::LinuxBoot => { + configure_64bit_boot(guest_mem, cmdline_addr, cmdline_size, initrd)?; + } + } + + Ok(()) +} + +fn configure_pvh( + guest_mem: &GuestMemoryMmap, + cmdline_addr: GuestAddress, + initrd: &Option, +) -> Result<(), ConfigurationError> { + const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336e_c578; + let first_addr_past_32bits = GuestAddress(FIRST_ADDR_PAST_32BITS); + let end_32bit_gap_start = GuestAddress(MMIO_MEM_START); + let himem_start = GuestAddress(layout::HIMEM_START); + + // Vector to hold modules (currently either empty or holding initrd). + let mut modules: Vec = Vec::new(); + if let Some(initrd_config) = initrd { + // The initrd has been written to guest memory already, here we just need to + // create the module structure that describes it. + modules.push(hvm_modlist_entry { + paddr: initrd_config.address.raw_value(), + size: initrd_config.size as u64, + ..Default::default() + }); + } + + // Vector to hold the memory maps which needs to be written to guest memory + // at MEMMAP_START after all of the mappings are recorded. + let mut memmap: Vec = Vec::new(); + + // Create the memory map entries. + memmap.push(hvm_memmap_table_entry { + addr: 0, + size: SYSTEM_MEM_START, + type_: MEMMAP_TYPE_RAM, + ..Default::default() + }); + memmap.push(hvm_memmap_table_entry { + addr: SYSTEM_MEM_START, + size: SYSTEM_MEM_SIZE, + type_: E820_RESERVED, + ..Default::default() + }); + let last_addr = guest_mem.last_addr(); + if last_addr < end_32bit_gap_start { + memmap.push(hvm_memmap_table_entry { + addr: himem_start.raw_value(), + size: last_addr.unchecked_offset_from(himem_start) + 1, + type_: MEMMAP_TYPE_RAM, + ..Default::default() + }); + } else { + memmap.push(hvm_memmap_table_entry { + addr: himem_start.raw_value(), + size: end_32bit_gap_start.unchecked_offset_from(himem_start), + type_: MEMMAP_TYPE_RAM, + ..Default::default() + }); + + if last_addr > first_addr_past_32bits { + memmap.push(hvm_memmap_table_entry { + addr: first_addr_past_32bits.raw_value(), + size: last_addr.unchecked_offset_from(first_addr_past_32bits) + 1, + type_: MEMMAP_TYPE_RAM, + ..Default::default() + }); + } + } + + // Construct the hvm_start_info structure and serialize it into + // boot_params. This will be stored at PVH_INFO_START address, and %rbx + // will be initialized to contain PVH_INFO_START prior to starting the + // guest, as required by the PVH ABI. + #[allow(clippy::cast_possible_truncation)] // the vec lenghts are single digit integers + let mut start_info = hvm_start_info { + magic: XEN_HVM_START_MAGIC_VALUE, + version: 1, + cmdline_paddr: cmdline_addr.raw_value(), + memmap_paddr: layout::MEMMAP_START, + memmap_entries: memmap.len() as u32, + nr_modules: modules.len() as u32, + ..Default::default() + }; + if !modules.is_empty() { + start_info.modlist_paddr = layout::MODLIST_START; + } + let mut boot_params = + BootParams::new::(&start_info, GuestAddress(layout::PVH_INFO_START)); + + // Copy the vector with the memmap table to the MEMMAP_START address + // which is already saved in the memmap_paddr field of hvm_start_info struct. + boot_params.set_sections::(&memmap, GuestAddress(layout::MEMMAP_START)); + + // Copy the vector with the modules list to the MODLIST_START address. + // Note that we only set the modlist_paddr address if there is a nonzero + // number of modules, but serializing an empty list is harmless. + boot_params.set_modules::(&modules, GuestAddress(layout::MODLIST_START)); + + // Write the hvm_start_info struct to guest memory. + PvhBootConfigurator::write_bootparams(&boot_params, guest_mem) + .map_err(|_| ConfigurationError::StartInfoSetup) +} + +fn configure_64bit_boot( + guest_mem: &GuestMemoryMmap, + cmdline_addr: GuestAddress, + cmdline_size: usize, + initrd: &Option, ) -> Result<(), ConfigurationError> { const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55; const KERNEL_HDR_MAGIC: u32 = 0x5372_6448; @@ -127,9 +264,6 @@ pub fn configure_system( let himem_start = GuestAddress(layout::HIMEM_START); - // Note that this puts the mptable at the last 1k of Linux's 640k base RAM - mptable::setup_mptable(guest_mem, resource_allocator, num_cpus)?; - // Set the location of RSDP in Boot Parameters to help the guest kernel find it faster. let mut params = boot_params { acpi_rsdp_addr: layout::RSDP_ADDR, @@ -245,8 +379,15 @@ mod tests { let no_vcpus = 4; let gm = single_region_mem(0x10000); let mut resource_allocator = ResourceAllocator::new().unwrap(); - let config_err = - configure_system(&gm, &mut resource_allocator, GuestAddress(0), 0, &None, 1); + let config_err = configure_system( + &gm, + &mut resource_allocator, + GuestAddress(0), + 0, + &None, + 1, + BootProtocol::LinuxBoot, + ); assert_eq!( config_err.unwrap_err(), super::ConfigurationError::MpTableSetup(mptable::MptableError::NotEnoughMemory) @@ -263,6 +404,17 @@ mod tests { 0, &None, no_vcpus, + BootProtocol::LinuxBoot, + ) + .unwrap(); + configure_system( + &gm, + &mut resource_allocator, + GuestAddress(0), + 0, + &None, + no_vcpus, + BootProtocol::PvhBoot, ) .unwrap(); @@ -277,6 +429,17 @@ mod tests { 0, &None, no_vcpus, + BootProtocol::LinuxBoot, + ) + .unwrap(); + configure_system( + &gm, + &mut resource_allocator, + GuestAddress(0), + 0, + &None, + no_vcpus, + BootProtocol::PvhBoot, ) .unwrap(); @@ -291,6 +454,17 @@ mod tests { 0, &None, no_vcpus, + BootProtocol::LinuxBoot, + ) + .unwrap(); + configure_system( + &gm, + &mut resource_allocator, + GuestAddress(0), + 0, + &None, + no_vcpus, + BootProtocol::PvhBoot, ) .unwrap(); } diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index cbcae8c0dd9..9e583f49cc1 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -827,6 +827,7 @@ pub fn configure_system_for_boot( cmdline_size, initrd, vcpu_config.vcpu_count, + entry_point.protocol, ) .map_err(ConfigureSystem)?; From 9fd0e9cad8294be129a42b75fbae32ef48b293fa Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Fri, 30 Dec 2022 14:54:28 -0800 Subject: [PATCH 268/464] test_licenses: Accept Oracle copyright The PVH boot support bits are under Oracle copyright. Signed-off-by: Colin Percival --- tests/integration_tests/style/test_licenses.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/integration_tests/style/test_licenses.py b/tests/integration_tests/style/test_licenses.py index c95181850f7..182c501da00 100644 --- a/tests/integration_tests/style/test_licenses.py +++ b/tests/integration_tests/style/test_licenses.py @@ -29,6 +29,10 @@ INTEL_LICENSE = "SPDX-License-Identifier: Apache-2.0" RIVOS_COPYRIGHT = "Copyright © 2023 Rivos, Inc." RIVOS_LICENSE = "SPDX-License-Identifier: Apache-2.0" +ORACLE_COPYRIGHT = "Copyright © 2020, Oracle and/or its affiliates." +ORACLE_LICENSE = "SPDX-License-Identifier: Apache-2.0" + +EXCLUDE = ["build", ".kernel", ".git"] def _has_amazon_copyright(string): @@ -90,6 +94,10 @@ def _validate_license(filename): file, RIVOS_LICENSE ) + has_oracle_copyright = ORACLE_COPYRIGHT in copyright_info and _look_for_license( + file, ORACLE_LICENSE + ) + return ( has_amazon_copyright or has_chromium_copyright @@ -97,6 +105,7 @@ def _validate_license(filename): or has_alibaba_copyright or has_intel_copyright or has_rivos_copyright + or has_oracle_copyright ) From afa43efe7dfa6e8bb908706d92f81de36abac770 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Fri, 14 Jul 2023 14:48:06 -0700 Subject: [PATCH 269/464] Add FreeBSD kernel+rootfs build instructions While I'm here, clarify that the existing instructions are for building a Linux kernel and rootfs. Signed-off-by: Colin Percival --- docs/rootfs-and-kernel-setup.md | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/rootfs-and-kernel-setup.md b/docs/rootfs-and-kernel-setup.md index 4a64fcec1bb..8dc10f55f87 100644 --- a/docs/rootfs-and-kernel-setup.md +++ b/docs/rootfs-and-kernel-setup.md @@ -1,6 +1,6 @@ # Creating Custom rootfs and kernel Images -## Creating a kernel Image +## Creating a Linux kernel Image ### Manual compilation @@ -79,7 +79,7 @@ but without ACPI support) and `6.1`. After the command finishes, the kernels along with the corresponding KConfig used will be stored under `resources/$(uname -m)`. -## Creating a rootfs Image +## Creating a Linux rootfs Image A rootfs image is just a file system image, that hosts at least an init system. For instance, our getting started guide uses an ext4 filesystem image. Note @@ -185,3 +185,44 @@ adjust the script(s) to suit your use case. You should now have a rootfs image (`ubuntu-22.04.ext4`), that you can boot with Firecracker. + +## Creating FreeBSD rootfs and kernel Images + +Here's a quick step-by-step guide to building a FreeBSD rootfs and kernel that +Firecracker can boot: + +1. Boot a FreeBSD system. In EC2, the + [FreeBSD 13 Marketplace image](https://aws.amazon.com/marketplace/pp/prodview-ukzmy5dzc6nbq) + is a good option; you can also use weekly snapshot AMIs published by the + FreeBSD project. (Firecracker support is in FreeBSD 14 and later, so you'll + need FreeBSD 13 or later to build it.) + + The build will require about 50 GB of disk space, so size the disk + appropriately. + +1. Log in to the FreeBSD system and become root. If using EC2, you'll want to + ssh in as `ec2-user` with your chosen SSH key and then `su` to become root. + +1. Install git and check out the FreeBSD src tree: + + ```sh + pkg install -y git + git clone https://git.freebsd.org/src.git /usr/src + ``` + + Firecracker support is available since FreeBSD 14.0 (released November 2023). + +1. Build FreeBSD: + + ```sh + make -C /usr/src buildworld buildkernel KERNCONF=FIRECRACKER + make -C /usr/src/release firecracker DESTDIR=`pwd` + ``` + +You should now have a rootfs `freebsd-rootfs.bin` and a kernel +`freebsd-kern.bin` in the current directory (or elsewhere if you change the +`DESTDIR` value) that you can boot with Firecracker. Note that the FreeBSD +rootfs generated in this manner is somewhat minimized compared to "stock" +FreeBSD; it omits utilities which are only relevant on physical systems (e.g., +utilities related to floppy disks, USB devices, and some network interfaces) and +also debug files and the system compiler. From d61624dda4a3900507c925cf32c53194bbbd20d6 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Fri, 14 Jul 2023 16:02:11 -0700 Subject: [PATCH 270/464] Add docs/pvh.md Brief description of the PVH boot mode. We defer to Xen for technical details of how CPU registers are set up upon kernel entry. Signed-off-by: Colin Percival Signed-off-by: Patrick Roy --- docs/pvh.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/pvh.md diff --git a/docs/pvh.md b/docs/pvh.md new file mode 100644 index 00000000000..1cef74a2389 --- /dev/null +++ b/docs/pvh.md @@ -0,0 +1,15 @@ +# PVH boot mode + +Firecracker supports booting x86 kernels in "PVH direct boot" mode +[as specified by the Xen project](https://github.com/xen-project/xen/blob/master/docs/misc/pvh.pandoc). +If a kernel is provided which contains the XEN_ELFNOTE_PHYS32_ENTRY ELF Note +then this boot mode will be used. This boot mode was designed for virtualized +environments which load the kernel directly, and is simpler than the "Linux +boot" mode which is designed to be launched from a legacy boot loader. + +PVH boot mode can be enabled for Linux by setting `CONFIG_PVH=y` in the kernel +configuration. (This is not the default setting.) + +PVH boot mode is enabled by default in FreeBSD, which has support for +Firecracker starting with FreeBSD 14.0. Instructions on building a FreeBSD +kernel and root filesystem are available [here](rootfs-and-kernel-setup.md). From 8fe4982b9600ff38575a7f04611c1a7b1368999e Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Fri, 14 Jul 2023 16:03:10 -0700 Subject: [PATCH 271/464] CHANGELOG: Mention PVH boot mode Firecracker now supports PVH boot as an alternative to "Linux" boot on the x86_64 architecture. This makes it possible for FreeBSD to boot, and also affects how Linux kernels compiled with the CONFIG_PVH=y option boot. Signed-off-by: Colin Percival Signed-off-by: Patrick Roy --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64034de9932..96d3f2a7a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,11 @@ and this project adheres to kernels. For older kernels physical counter will still be passed to the guest unmodified. See more info [here](https://github.com/firecracker-microvm/firecracker/blob/main/docs/prod-host-setup.md#arm-only-vm-physical-counter-behaviour) +- [#5048](https://github.com/firecracker-microvm/firecracker/pull/5048): Added + support for [PVH boot mode](docs/pvh.md). This is used when an x86 kernel + provides the appropriate ELF Note to indicate that PVH boot mode is supported. + Linux kernels newer than 5.0 compiled with `CONFIG_PVH=y` set this ELF Note, + as do FreeBSD kernels. ### Changed From c52bde13de7b98e399ba2f4acca4ad6585c0cba7 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 11 Nov 2024 13:04:00 +0000 Subject: [PATCH 272/464] test: verify PVH boot protocol is used Use test_api_happy_start to assert that the log message that indicates usage of PVH boot protocol is present. Only x86_64 guests support PVH boot, and on ARM we do not emit any log messages, so restrict the assertion to x86_64 platforms. Signed-off-by: Patrick Roy --- tests/framework/utils.py | 5 +++++ tests/integration_tests/functional/test_api.py | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/framework/utils.py b/tests/framework/utils.py index 093667f5743..d7ecb00c7cd 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -614,3 +614,8 @@ def __enter__(self): def __exit__(self, _type, _value, _traceback): signal.alarm(0) + + +def pvh_supported() -> bool: + """Checks if PVH boot is supported""" + return platform.architecture() == "x86_64" diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 94166374bd3..369ae659877 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -16,7 +16,7 @@ import host_tools.drive as drive_tools import host_tools.network as net_tools -from framework import utils_cpuid +from framework import utils, utils_cpuid from framework.utils import get_firecracker_version_from_toml, is_io_uring_supported MEM_LIMIT = 1000000000 @@ -42,6 +42,9 @@ def test_api_happy_start(uvm_plain): test_microvm.start() + if utils.pvh_supported(): + assert "Kernel loaded using PVH boot protocol" in test_microvm.log_data + def test_drive_io_engine(uvm_plain): """ From e9046496c8d0f256ed450767754b1804213f604f Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 11 Nov 2024 13:17:02 +0000 Subject: [PATCH 273/464] fix: dont hardcode "main" in gitlint test Hardcoding main means the test looks at the wrong range of commits for feature branches, which can result in problem if feature branches are long-lived. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_gitlint.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/style/test_gitlint.py b/tests/integration_tests/style/test_gitlint.py index b47286d33e9..b7ef8631327 100644 --- a/tests/integration_tests/style/test_gitlint.py +++ b/tests/integration_tests/style/test_gitlint.py @@ -5,6 +5,7 @@ import os from framework import utils +from framework.ab_test import DEFAULT_A_REVISION def test_gitlint(): @@ -15,6 +16,6 @@ def test_gitlint(): os.environ["LANG"] = "C.UTF-8" rc, _, stderr = utils.run_cmd( - "gitlint --commits origin/main..HEAD -C ../.gitlint --extra-path framework/gitlint_rules.py", + f"gitlint --commits origin/{DEFAULT_A_REVISION}..HEAD -C ../.gitlint --extra-path framework/gitlint_rules.py", ) assert rc == 0, "Commit message violates gitlint rules: {}".format(stderr) From 38a6faffa84cae7d033ee5d7b44d1ae78624693b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Feb 2025 14:25:03 +0000 Subject: [PATCH 274/464] test: skip test_gitlint on PR #5048 PR #5048 is the merge of the long-lived PVH feature branch. The commits on this branch were made long before we changes the gitlint rules to more closely follow Linux rules when it comes to sign-offs from co-authors (as used to not only not require them, but not allow them in the first place, meaning the first 3 commit in this PR are only signed by of Colin and me, but not the coauthor from a few years ago). Explicitly skip this test for this one PR. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_gitlint.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration_tests/style/test_gitlint.py b/tests/integration_tests/style/test_gitlint.py index b7ef8631327..1a323b53186 100644 --- a/tests/integration_tests/style/test_gitlint.py +++ b/tests/integration_tests/style/test_gitlint.py @@ -4,10 +4,16 @@ import os +import pytest + from framework import utils from framework.ab_test import DEFAULT_A_REVISION +@pytest.mark.skipif( + os.environ.get("BUILDKITE_PULL_REQUEST") == "5048", + reason="PR of a feature branch from before this test was modified to follow Linux sign-off rules for co-authors.", +) def test_gitlint(): """ Test that all commit messages pass the gitlint rules. From a24bae5121f9c082ddf66bb4a7e146c2fda531d2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 6 Mar 2025 17:03:02 +0000 Subject: [PATCH 275/464] Revert "test: skip test_gitlint on PR #5048" This reverts commit 38a6faffa84cae7d033ee5d7b44d1ae78624693b. Signed-off-by: Patrick Roy --- tests/integration_tests/style/test_gitlint.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/integration_tests/style/test_gitlint.py b/tests/integration_tests/style/test_gitlint.py index 1a323b53186..b7ef8631327 100644 --- a/tests/integration_tests/style/test_gitlint.py +++ b/tests/integration_tests/style/test_gitlint.py @@ -4,16 +4,10 @@ import os -import pytest - from framework import utils from framework.ab_test import DEFAULT_A_REVISION -@pytest.mark.skipif( - os.environ.get("BUILDKITE_PULL_REQUEST") == "5048", - reason="PR of a feature branch from before this test was modified to follow Linux sign-off rules for co-authors.", -) def test_gitlint(): """ Test that all commit messages pass the gitlint rules. From 8da9fc913507d5aefe91b023f51ac8c4d7306ce9 Mon Sep 17 00:00:00 2001 From: Gudmundur Bjarni Olafsson Date: Wed, 5 Mar 2025 05:26:15 +0100 Subject: [PATCH 276/464] fix: Allow jailer to continue with partial CPU cache info If CPU caching information is missing, this change allows the jailer to still continue, and fall through to the validation logic in firecracker. Signed-off-by: Gudmundur Bjarni Olafsson --- src/jailer/src/env.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index d2e9a80711a..c01390e3fd5 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -574,17 +574,20 @@ impl Env { let host_cache_file = host_path.join(entry); let jailer_cache_file = jailer_path.join(entry); - let line = readln_special(&host_cache_file)?; - writeln_special(&jailer_cache_file, line)?; - - // We now change the permissions. - let dest_path_cstr = to_cstring(&jailer_cache_file)?; - // SAFETY: Safe because dest_path_cstr is null-terminated. - SyscallReturnCode(unsafe { - libc::chown(dest_path_cstr.as_ptr(), self.uid(), self.gid()) - }) - .into_empty_result() - .map_err(|err| JailerError::ChangeFileOwner(jailer_cache_file.to_owned(), err))?; + if let Ok(line) = readln_special(&host_cache_file) { + writeln_special(&jailer_cache_file, line)?; + + // We now change the permissions. + let dest_path_cstr = to_cstring(&jailer_cache_file)?; + // SAFETY: Safe because dest_path_cstr is null-terminated. + SyscallReturnCode(unsafe { + libc::chown(dest_path_cstr.as_ptr(), self.uid(), self.gid()) + }) + .into_empty_result() + .map_err(|err| { + JailerError::ChangeFileOwner(jailer_cache_file.to_owned(), err) + })?; + } } } Ok(()) From 83119b8ad9f7bfd613d9d5d43bb0ee7426b50ab6 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 6 Mar 2025 10:56:55 +0000 Subject: [PATCH 277/464] feat: add option to not add kani bk step In some cases running kani steps is not useful and only results in longer pipeline runs. Add option to disable it if needed. Signed-off-by: Egor Lazarchuk --- .buildkite/common.py | 6 ++++++ .buildkite/pipeline_pr.py | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index bda1ec9eccf..4bacff75f1e 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -178,6 +178,12 @@ def __call__(self, parser, namespace, value, option_string=None): default=None, type=str, ) +COMMON_PARSER.add_argument( + "--no-kani", + help="Don't add kani step", + action="store_true", + default=False, +) def random_str(k: int): diff --git a/.buildkite/pipeline_pr.py b/.buildkite/pipeline_pr.py index 5b4693f51bd..46a8f6880be 100755 --- a/.buildkite/pipeline_pr.py +++ b/.buildkite/pipeline_pr.py @@ -48,8 +48,9 @@ "./tools/devtool -y make_release", ) -if not changed_files or any( - x.suffix in [".rs", ".toml", ".lock"] for x in changed_files +if not pipeline.args.no_kani and ( + not changed_files + or any(x.suffix in [".rs", ".toml", ".lock"] for x in changed_files) ): kani_grp = pipeline.build_group( "🔍 Kani", From ed0d202f43987f5f01c0db47a35826352e5bfae6 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 6 Mar 2025 11:03:34 +0000 Subject: [PATCH 278/464] chore: increase timeout for kani tests Kani tests run very close to the current timeout values. Increase timeout to 1h. Signed-off-by: Egor Lazarchuk --- tests/integration_tests/test_kani.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/test_kani.py b/tests/integration_tests/test_kani.py index 35c84e105b6..0583fa4837b 100644 --- a/tests/integration_tests/test_kani.py +++ b/tests/integration_tests/test_kani.py @@ -13,10 +13,12 @@ PLATFORM = platform.machine() +TIMEOUT = 3600 + # The `check_output` timeout will always fire before this one, but we need to # set a timeout here to override the default pytest timeout of 180s. -@pytest.mark.timeout(2420) +@pytest.mark.timeout(TIMEOUT) @pytest.mark.skipif( os.environ.get("BUILDKITE") != "true", reason="Kani's memory requirements likely cannot be satisfied locally", @@ -33,7 +35,7 @@ def test_kani(results_dir): # --enable-unstable is needed to enable `-Z` flags _, stdout, _ = utils.check_output( "cargo kani --enable-unstable -Z stubbing -Z function-contracts --restrict-vtable -j --output-format terse", - timeout=2400, + timeout=TIMEOUT, ) (results_dir / "kani_log").write_text(stdout, encoding="utf-8") From 07ccd0d4e97fb65410f31c02bb445d7c8086d222 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 6 Mar 2025 15:07:26 +0000 Subject: [PATCH 279/464] refactor(jailer): proper path creation Create executable path without push/pop dance. Signed-off-by: Egor Lazarchuk --- src/jailer/src/env.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index c01390e3fd5..c987716a1a1 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -478,12 +478,7 @@ impl Env { .exec_file_path .file_name() .ok_or_else(|| JailerError::ExtractFileName(self.exec_file_path.clone()))?; - // We do a quick push here to get the global path of the executable inside the chroot, - // without having to create a new PathBuf. We'll then do a pop to revert to the actual - // chroot_dir right after the copy. - // TODO: just now wondering ... is doing a push()/pop() thing better than just creating - // a new PathBuf, with something like chroot_dir.join(exec_file_name) ?! - self.chroot_dir.push(exec_file_name); + let jailer_exec_file_path = self.chroot_dir.join(exec_file_name); // We do a copy instead of a hard-link for 2 reasons // 1. hard-linking is not possible if the file is in another device @@ -491,13 +486,15 @@ impl Env { // Firecracker binary (like the executable .text section), this latter part is not // desirable in Firecracker's threat model. Copying prevents 2 Firecracker processes from // sharing memory. - fs::copy(&self.exec_file_path, &self.chroot_dir).map_err(|err| { - JailerError::Copy(self.exec_file_path.clone(), self.chroot_dir.clone(), err) + fs::copy(&self.exec_file_path, &jailer_exec_file_path).map_err(|err| { + JailerError::Copy( + self.exec_file_path.clone(), + jailer_exec_file_path.clone(), + err, + ) })?; - // Pop exec_file_name. - self.chroot_dir.pop(); - Ok(exec_file_name.to_os_string()) + Ok(exec_file_name.to_owned()) } fn join_netns(path: &str) -> Result<(), JailerError> { From cc5d6b4030041f16c28ed5f7452b7e59e7e003d3 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 7 Mar 2025 14:20:46 +0000 Subject: [PATCH 280/464] refactor(jailer): remove arch dependent ptr cast There is no need to do different cast types for different platforms. Signed-off-by: Egor Lazarchuk --- src/jailer/src/env.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index c987716a1a1..45ede2f3434 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -463,12 +463,8 @@ impl Env { .map_err(|err| JailerError::Chmod(folder_path.to_owned(), err))?; let c_path = CString::new(folder_path.to_str().unwrap()).unwrap(); - #[cfg(target_arch = "x86_64")] - let folder_bytes_ptr = c_path.as_ptr().cast::(); - #[cfg(target_arch = "aarch64")] - let folder_bytes_ptr = c_path.as_ptr(); // SAFETY: This is safe because folder was checked for a null-terminator. - SyscallReturnCode(unsafe { libc::chown(folder_bytes_ptr, self.uid(), self.gid()) }) + SyscallReturnCode(unsafe { libc::chown(c_path.as_ptr(), self.uid(), self.gid()) }) .into_empty_result() .map_err(|err| JailerError::ChangeFileOwner(folder_path.to_owned(), err)) } From 3e688638ea09835e9df107e816057abc89aecb77 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 12:05:36 +0000 Subject: [PATCH 281/464] refactor(test): stop hardcoding uffd socket path everywhere Instead use the property of the `UffdHandler` object that `spawn_uffd_handler` returns. Signed-off-by: Patrick Roy --- tests/framework/utils_uffd.py | 6 +++--- .../integration_tests/functional/test_uffd.py | 12 +++++++----- .../performance/test_huge_pages.py | 18 +++++++++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py index 9de89809a20..690eb423573 100644 --- a/tests/framework/utils_uffd.py +++ b/tests/framework/utils_uffd.py @@ -21,7 +21,7 @@ def __init__(self, name, socket_path, mem_file, chroot_path, log_file_name): """Instantiate the handler process with arguments.""" self._proc = None self._handler_name = name - self._socket_path = socket_path + self.socket_path = socket_path self._mem_file = mem_file self._chroot = chroot_path self._log_file = log_file_name @@ -35,7 +35,7 @@ def spawn(self, uid, gid): chroot_log_file = Path("/") / self._log_file with open(chroot_log_file, "w", encoding="utf-8") as logfile: - args = [f"/{self._handler_name}", self._socket_path, self._mem_file] + args = [f"/{self._handler_name}", self.socket_path, self._mem_file] self._proc = subprocess.Popen( args, stdout=logfile, stderr=subprocess.STDOUT ) @@ -48,7 +48,7 @@ def spawn(self, uid, gid): # The page fault handler will create the socket path with root rights. # Change rights to the jailer's. - os.chown(self._socket_path, uid, gid) + os.chown(self.socket_path, uid, gid) @property def proc(self): diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index cb5ac0c44c9..35b03d7aa34 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -9,7 +9,7 @@ import requests from framework.utils import Timeout, check_output -from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler, uffd_handler +from framework.utils_uffd import spawn_pf_handler, uffd_handler @pytest.fixture(scope="function", name="snapshot") @@ -92,9 +92,9 @@ def test_valid_handler(uvm_plain, snapshot): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) + vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) # Inflate balloon. vm.api.balloon.patch(amount_mib=200) @@ -125,13 +125,15 @@ def test_malicious_handler(uvm_plain, snapshot): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler(vm, uffd_handler("malicious"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("malicious"), snapshot.mem) # We expect Firecracker to freeze while resuming from a snapshot # due to the malicious handler's unavailability. try: with Timeout(seconds=30): - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) + vm.restore_from_snapshot( + snapshot, resume=True, uffd_path=pf_handler.socket_path + ) assert False, "Firecracker should freeze" except (TimeoutError, requests.exceptions.ReadTimeout): pass diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 65ae2e6fbc2..acfee58139d 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -10,7 +10,7 @@ from framework.microvm import HugePagesConfig from framework.properties import global_props from framework.utils_ftrace import ftrace_events -from framework.utils_uffd import SOCKET_PATH, spawn_pf_handler, uffd_handler +from framework.utils_uffd import spawn_pf_handler, uffd_handler def check_hugetlbfs_in_use(pid: int, allocation_name: str): @@ -93,9 +93,9 @@ def test_hugetlbfs_snapshot(microvm_factory, guest_kernel_linux_5_10, rootfs): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) + vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) check_hugetlbfs_in_use(vm.firecracker_pid, "/anon_hugepage") @@ -135,9 +135,11 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain): vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot_merged.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot_merged.mem) - vm.restore_from_snapshot(snapshot_merged, resume=True, uffd_path=SOCKET_PATH) + vm.restore_from_snapshot( + snapshot_merged, resume=True, uffd_path=pf_handler.socket_path + ) # Verify if the restored microvm works. @@ -193,10 +195,12 @@ def test_ept_violation_count( vm.spawn() # Spawn page fault handler process. - _pf_handler = spawn_pf_handler(vm, uffd_handler("fault_all"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("fault_all"), snapshot.mem) with ftrace_events("kvm:*"): - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=SOCKET_PATH) + vm.restore_from_snapshot( + snapshot, resume=True, uffd_path=pf_handler.socket_path + ) # Verify if guest can run commands, and also wake up the fast page fault helper to trigger page faults. vm.ssh.check_output(f"kill -s {signal.SIGUSR1} {pid}") From a7b16d04ee7b5cdbd98adec4357209d3e091ede4 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 11:42:47 +0000 Subject: [PATCH 282/464] test: have fast_page_fault_helper print time memset took The memset causes page faults in the guest which will be handled by UFFD. By timing the memset from inside the guest, we can measure the latency of these page faults as observed by an application running inside the guest. Signed-off-by: Patrick Roy --- .../usr/local/bin/fast_page_fault_helper.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index 591ac3b9612..96e565f0c3f 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -10,17 +10,23 @@ // This way, the `memset` will trigger a fast page fault for every page in // the memory region. -#include // perror +#include // perror, fopen, fprintf #include // sigwait and friends #include // memset #include // mmap +#include // clock_gettime +#include // open #define MEM_SIZE_MIB (128 * 1024 * 1024) +#define NANOS_PER_SEC 1000000000 -int main(int argc, char *const argv[]) { +int main() { sigset_t set; int signal; void *ptr; + struct timespec start, end; + long duration_nanos; + FILE *out_file; sigemptyset(&set); if (sigaddset(&set, SIGUSR1) == -1) { @@ -43,7 +49,23 @@ int main(int argc, char *const argv[]) { sigwait(&set, &signal); + clock_gettime(CLOCK_BOOTTIME, &start); memset(ptr, 2, MEM_SIZE_MIB); + clock_gettime(CLOCK_BOOTTIME, &end); + + duration_nanos = (end.tv_sec - start.tv_sec) * NANOS_PER_SEC + end.tv_nsec - start.tv_nsec; + + out_file = fopen("/tmp/fast_page_fault_helper.out", "w"); + if (out_file == NULL) { + perror("fopen"); + return 1; + } + + fprintf(out_file, "%ld", duration_nanos); + if (fclose(out_file)) { + perror("fclose"); + return 1; + } return 0; } \ No newline at end of file From e326b3520fb33a41fcde321f051b08c383e8153f Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 12:48:54 +0000 Subject: [PATCH 283/464] refactor(uffd): Make example UFFD fast in absense of balloon device Make the example UFFD handler use a HashSet to only store address ranges that were actually removed due to expanding memory balloon. This eliminates the HashMap that previously held entries for every single page in guest memory, which was causing the example uffd handler to slow to a crawl (taking about 40s to fault in 128MB of memory). This is possible because the UFFD handler doesn't actually care about the 4 states a page can supposedly be in, it only needs to know whether a page needs to be served from the memory snapshot file, or zeroed out. Since zero-ing out is the rarer of the two (only happens if a balloon device caused some previously faulted in memory to be madvise'd away), we only store information about pages that we got remove messages about, and simply assume every other page needs to be served from the snapshot file. This means that in the happy path of "no balloon device", we never need to store any information about the memory at all. This one simple optimization brings the fault time down to 500ms (from 40s) for the 128MB scenario, which makes the example handler usable for performance tests for page fault latencies. Signed-off-by: Patrick Roy --- .../examples/uffd/fault_all_handler.rs | 3 +- src/firecracker/examples/uffd/uffd_utils.rs | 121 +++++------------- .../examples/uffd/valid_handler.rs | 7 +- 3 files changed, 40 insertions(+), 91 deletions(-) diff --git a/src/firecracker/examples/uffd/fault_all_handler.rs b/src/firecracker/examples/uffd/fault_all_handler.rs index cfeaa099236..d0f127a8ce1 100644 --- a/src/firecracker/examples/uffd/fault_all_handler.rs +++ b/src/firecracker/examples/uffd/fault_all_handler.rs @@ -35,8 +35,7 @@ fn main() { match event { userfaultfd::Event::Pagefault { .. } => { for region in uffd_handler.mem_regions.clone() { - uffd_handler - .serve_pf(region.mapping.base_host_virt_addr as _, region.mapping.size); + uffd_handler.serve_pf(region.base_host_virt_addr as _, region.size); } } _ => panic!("Unexpected event on userfaultfd"), diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index a2f7879f591..dcc05151967 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -4,7 +4,7 @@ // Not everything is used by both binaries #![allow(dead_code)] -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fs::File; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; use std::os::unix::net::UnixStream; @@ -34,26 +34,20 @@ pub struct GuestRegionUffdMapping { pub page_size_kib: usize, } -#[derive(Debug, Clone, Copy)] -pub enum MemPageState { - Uninitialized, - FromFile, - Removed, - Anonymous, -} - -#[derive(Debug, Clone)] -pub struct MemRegion { - pub mapping: GuestRegionUffdMapping, - page_states: HashMap, +impl GuestRegionUffdMapping { + fn contains(&self, fault_page_addr: u64) -> bool { + fault_page_addr >= self.base_host_virt_addr + && fault_page_addr < self.base_host_virt_addr + self.size as u64 + } } #[derive(Debug)] pub struct UffdHandler { - pub mem_regions: Vec, + pub mem_regions: Vec, pub page_size: usize, backing_buffer: *const u8, uffd: Uffd, + removed_pages: HashSet, } impl UffdHandler { @@ -92,13 +86,12 @@ impl UffdHandler { let uffd = unsafe { Uffd::from_raw_fd(file.into_raw_fd()) }; - let mem_regions = create_mem_regions(&mappings, page_size); - Self { - mem_regions, + mem_regions: mappings, page_size, backing_buffer, uffd, + removed_pages: HashSet::new(), } } @@ -106,13 +99,12 @@ impl UffdHandler { self.uffd.read_event() } - pub fn update_mem_state_mappings(&mut self, start: u64, end: u64, state: MemPageState) { - for region in self.mem_regions.iter_mut() { - for (key, value) in region.page_states.iter_mut() { - if key >= &start && key < &end { - *value = state; - } - } + pub fn mark_range_removed(&mut self, start: u64, end: u64) { + let pfn_start = start / self.page_size as u64; + let pfn_end = end / self.page_size as u64; + + for pfn in pfn_start..pfn_end { + self.removed_pages.insert(pfn); } } @@ -120,33 +112,16 @@ impl UffdHandler { // Find the start of the page that the current faulting address belongs to. let dst = (addr as usize & !(self.page_size - 1)) as *mut libc::c_void; let fault_page_addr = dst as u64; - - // Get the state of the current faulting page. - for region in self.mem_regions.iter() { - match region.page_states.get(&fault_page_addr) { - // Our simple PF handler has a simple strategy: - // There exist 4 states in which a memory page can be in: - // 1. Uninitialized - page was never touched - // 2. FromFile - the page is populated with content from snapshotted memory file - // 3. Removed - MADV_DONTNEED was called due to balloon inflation - // 4. Anonymous - page was zeroed out -> this implies that more than one page fault - // event was received. This can be a consequence of guest reclaiming back its - // memory from the host (through balloon device) - Some(MemPageState::Uninitialized) | Some(MemPageState::FromFile) => { - match self.populate_from_file(region, fault_page_addr, len) { - Some((start, end)) => { - self.update_mem_state_mappings(start, end, MemPageState::FromFile) - } - None => return false, - } - return true; - } - Some(MemPageState::Removed) | Some(MemPageState::Anonymous) => { - let (start, end) = self.zero_out(fault_page_addr); - self.update_mem_state_mappings(start, end, MemPageState::Anonymous); - return true; + let fault_pfn = fault_page_addr / self.page_size as u64; + + if self.removed_pages.contains(&fault_pfn) { + self.zero_out(fault_page_addr); + return true; + } else { + for region in self.mem_regions.iter() { + if region.contains(fault_page_addr) { + return self.populate_from_file(region, fault_page_addr, len); } - None => {} } } @@ -156,13 +131,14 @@ impl UffdHandler { ); } - fn populate_from_file(&self, region: &MemRegion, dst: u64, len: usize) -> Option<(u64, u64)> { - let offset = dst - region.mapping.base_host_virt_addr; - let src = self.backing_buffer as u64 + region.mapping.offset + offset; + fn populate_from_file(&self, region: &GuestRegionUffdMapping, dst: u64, len: usize) -> bool { + let offset = dst - region.base_host_virt_addr; + let src = self.backing_buffer as u64 + region.offset + offset; - let ret = unsafe { + unsafe { match self.uffd.copy(src as *const _, dst as *mut _, len, true) { - Ok(value) => value, + // Make sure the UFFD copied some bytes. + Ok(value) => assert!(value > 0), // Catch EAGAIN errors, which occur when a `remove` event lands in the UFFD // queue while we're processing `pagefault` events. // The weird cast is because the `bytes_copied` field is based on the @@ -172,12 +148,12 @@ impl UffdHandler { Err(Error::PartiallyCopied(bytes_copied)) if bytes_copied == 0 || bytes_copied == (-libc::EAGAIN) as usize => { - return None + return false } Err(Error::CopyFailed(errno)) if std::io::Error::from(errno).raw_os_error().unwrap() == libc::EEXIST => { - len + () } Err(e) => { panic!("Uffd copy failed: {e:?}"); @@ -185,13 +161,10 @@ impl UffdHandler { } }; - // Make sure the UFFD copied some bytes. - assert!(ret > 0); - - Some((dst, dst + len as u64)) + true } - fn zero_out(&mut self, addr: u64) -> (u64, u64) { + fn zero_out(&mut self, addr: u64) { let ret = unsafe { self.uffd .zeropage(addr as *mut _, self.page_size, true) @@ -199,8 +172,6 @@ impl UffdHandler { }; // Make sure the UFFD zeroed out some bytes. assert!(ret > 0); - - (addr, addr + self.page_size as u64) } } @@ -345,28 +316,6 @@ impl Runtime { } } -fn create_mem_regions(mappings: &Vec, page_size: usize) -> Vec { - let mut mem_regions: Vec = Vec::with_capacity(mappings.len()); - - for r in mappings.iter() { - let mapping = r.clone(); - let mut addr = r.base_host_virt_addr; - let end_addr = r.base_host_virt_addr + r.size as u64; - let mut page_states = HashMap::new(); - - while addr < end_addr { - page_states.insert(addr, MemPageState::Uninitialized); - addr += page_size as u64; - } - mem_regions.push(MemRegion { - mapping, - page_states, - }); - } - - mem_regions -} - #[cfg(test)] mod tests { use std::mem::MaybeUninit; diff --git a/src/firecracker/examples/uffd/valid_handler.rs b/src/firecracker/examples/uffd/valid_handler.rs index 936b9f517a3..3be958b3578 100644 --- a/src/firecracker/examples/uffd/valid_handler.rs +++ b/src/firecracker/examples/uffd/valid_handler.rs @@ -10,7 +10,7 @@ mod uffd_utils; use std::fs::File; use std::os::unix::net::UnixListener; -use uffd_utils::{MemPageState, Runtime, UffdHandler}; +use uffd_utils::{Runtime, UffdHandler}; fn main() { let mut args = std::env::args(); @@ -86,8 +86,9 @@ fn main() { deferred_events.push(event); } } - userfaultfd::Event::Remove { start, end } => uffd_handler - .update_mem_state_mappings(start as u64, end as u64, MemPageState::Removed), + userfaultfd::Event::Remove { start, end } => { + uffd_handler.mark_range_removed(start as u64, end as u64) + } _ => panic!("Unexpected event on userfaultfd"), } } From 4c362b140683e01583d71c725575e1da38ba5ad5 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 12:44:36 +0000 Subject: [PATCH 284/464] refactor(test): Store binary_dir inside microvm Just store the binary dir inside the microvm class instead of separate paths to firecracker and jailer binaries. This centralizes the existance assertions, but means we cant theoretically use jailer and firecracker binaries from different locations anymore (however, nothing in the test framework was doing this, as MicroVMFactory already did not support this and hardcoded the binary names relative to the --binary-dir option). Signed-off-by: Patrick Roy --- tests/conftest.py | 17 +++++++---------- tests/framework/defs.py | 7 +++++++ tests/framework/microvm.py | 18 +++++++++++++++--- tests/host_tools/cargo_build.py | 11 ----------- .../security/test_vulnerabilities.py | 6 ++---- tools/sandbox.py | 9 ++++----- .../test-docker-rootfs.py | 4 ++-- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fa309427ef1..fb0b88b677a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,6 +33,7 @@ import host_tools.cargo_build as build_tools from framework import defs, utils from framework.artifacts import disks, kernel_params +from framework.defs import DEFAULT_BINARY_DIR from framework.microvm import MicroVMFactory from framework.properties import global_props from framework.utils_cpu_templates import ( @@ -293,14 +294,11 @@ def get(self, _netns_id): def microvm_factory(request, record_property, results_dir, netns_factory): """Fixture to create microvms simply.""" - if binary_dir := request.config.getoption("--binary-dir"): - fc_binary_path = Path(binary_dir) / "firecracker" - jailer_binary_path = Path(binary_dir) / "jailer" - if not fc_binary_path.exists(): - raise RuntimeError("Firecracker binary does not exist") - else: - fc_binary_path, jailer_binary_path = build_tools.get_firecracker_binaries() - record_property("firecracker_bin", str(fc_binary_path)) + binary_dir = request.config.getoption("--binary-dir") or DEFAULT_BINARY_DIR + if isinstance(binary_dir, str): + binary_dir = Path(binary_dir) + + record_property("firecracker_bin", str(binary_dir / "firecracker")) # If `--custom-cpu-template` option is provided, the given CPU template will # be applied afterwards unless overwritten. @@ -316,8 +314,7 @@ def microvm_factory(request, record_property, results_dir, netns_factory): # We could override the chroot base like so # jailer_kwargs={"chroot_base": "/srv/jailo"} uvm_factory = MicroVMFactory( - fc_binary_path, - jailer_binary_path, + binary_dir, netns_factory=netns_factory, custom_cpu_template=custom_cpu_template, ) diff --git a/tests/framework/defs.py b/tests/framework/defs.py index f017dc231ee..38fbe6802df 100644 --- a/tests/framework/defs.py +++ b/tests/framework/defs.py @@ -26,6 +26,13 @@ # Absolute path to the test results folder TEST_RESULTS_DIR = FC_WORKSPACE_DIR / "test_results" +DEFAULT_BINARY_DIR = ( + LOCAL_BUILD_PATH + / "cargo_target" + / f"{platform.machine()}-unknown-linux-musl" + / "release" +) + # The minimum required host kernel version for which io_uring is supported in # Firecracker. MIN_KERNEL_VERSION_FOR_IO_URING = "5.10.51" diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index f93a0dabf19..85ed588b809 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -1073,13 +1073,25 @@ def wait_for_ssh_up(self): class MicroVMFactory: """MicroVM factory""" - def __init__(self, fc_binary_path: Path, jailer_binary_path: Path, **kwargs): + def __init__(self, binary_path: Path, **kwargs): self.vms = [] - self.fc_binary_path = Path(fc_binary_path) - self.jailer_binary_path = Path(jailer_binary_path) + self.binary_path = binary_path self.netns_factory = kwargs.pop("netns_factory", net_tools.NetNs) self.kwargs = kwargs + assert self.fc_binary_path.exists(), "missing firecracker binary" + assert self.jailer_binary_path.exists(), "missing jailer binary" + + @property + def fc_binary_path(self): + """The path to the firecracker binary from which this factory will build VMs""" + return self.binary_path / "firecracker" + + @property + def jailer_binary_path(self): + """The path to the jailer binary using which this factory will build VMs""" + return self.binary_path / "jailer" + def build(self, kernel=None, rootfs=None, **kwargs): """Build a microvm""" kwargs = self.kwargs | kwargs diff --git a/tests/host_tools/cargo_build.py b/tests/host_tools/cargo_build.py index 5a029f8c5f4..54302901211 100644 --- a/tests/host_tools/cargo_build.py +++ b/tests/host_tools/cargo_build.py @@ -65,17 +65,6 @@ def get_binary(name, *, workspace_dir=FC_WORKSPACE_DIR, example=None): return bin_path -def get_firecracker_binaries(*, workspace_dir=FC_WORKSPACE_DIR): - """Build the Firecracker and Jailer binaries if they don't exist. - - Returns the location of the firecracker related binaries eventually after - building them in case they do not exist at the specified root_path. - """ - return get_binary("firecracker", workspace_dir=workspace_dir), get_binary( - "jailer", workspace_dir=workspace_dir - ) - - def get_example(name, *args, package="firecracker", **kwargs): """Build an example binary""" return get_binary(package, *args, **kwargs, example=name) diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index a4461aded78..14307e56888 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -206,10 +206,8 @@ def microvm_factory_a(record_property): """MicroVMFactory using revision A binaries""" revision_a = global_props.buildkite_revision_a bin_dir = git_clone(Path("../build") / revision_a, revision_a).resolve() - fc_bin = bin_dir / "firecracker" - jailer_bin = bin_dir / "jailer" - record_property("firecracker_bin", str(fc_bin)) - uvm_factory = MicroVMFactory(fc_bin, jailer_bin) + record_property("firecracker_bin", str(bin_dir / "firecracker")) + uvm_factory = MicroVMFactory(bin_dir) yield uvm_factory uvm_factory.kill() diff --git a/tools/sandbox.py b/tools/sandbox.py index 3cdcec345a7..8cdf3277352 100755 --- a/tools/sandbox.py +++ b/tools/sandbox.py @@ -14,8 +14,8 @@ from pathlib import Path from framework.artifacts import disks, kernels +from framework.defs import DEFAULT_BINARY_DIR from framework.microvm import MicroVMFactory -from host_tools.cargo_build import get_firecracker_binaries kernels = list(kernels("vmlinux-*")) rootfs = list(disks("ubuntu*ext4")) @@ -61,17 +61,16 @@ def parse_byte_size(param): args = parser.parse_args() print(args) -bins = None +binary_dir = None if args.binary_dir: binary_dir = Path(args.binary_dir).resolve() - bins = binary_dir / "firecracker", binary_dir / "jailer" else: - bins = get_firecracker_binaries() + binary_dir = DEFAULT_BINARY_DIR cpu_template = None if args.cpu_template_path is not None: cpu_template = json.loads(args.cpu_template_path.read_text()) -vmfcty = MicroVMFactory(*bins) +vmfcty = MicroVMFactory(binary_dir) print(f"uvm with kernel {args.kernel} ...") uvm = vmfcty.build(args.kernel, args.rootfs) diff --git a/tools/test-popular-containers/test-docker-rootfs.py b/tools/test-popular-containers/test-docker-rootfs.py index aac24ac2ecc..1434e40173c 100755 --- a/tools/test-popular-containers/test-docker-rootfs.py +++ b/tools/test-popular-containers/test-docker-rootfs.py @@ -17,8 +17,8 @@ # pylint: disable=wrong-import-position from framework.artifacts import kernels +from framework.defs import DEFAULT_BINARY_DIR from framework.microvm import MicroVMFactory -from host_tools.cargo_build import get_firecracker_binaries # pylint: enable=wrong-import-position @@ -26,7 +26,7 @@ # Use the latest guest kernel kernel = kernels[-1] -vmfcty = MicroVMFactory(*get_firecracker_binaries()) +vmfcty = MicroVMFactory(DEFAULT_BINARY_DIR) # (may take a while to compile Firecracker...) for rootfs in Path(".").glob("*.ext4"): From 3f73d0390146ffd3f20abdf356c42395468a6f89 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 12:50:02 +0000 Subject: [PATCH 285/464] test: replace workspace_dir arg with binary_dir in get_binary Instead of get_binary assuming it always operates on a cargo build directory, have it directly operate on a "binary directory" in the sense of the --binary-dir parameter. Nothing was using the workspace_dir arg, so no functional changes. Signed-off-by: Patrick Roy --- tests/host_tools/cargo_build.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/host_tools/cargo_build.py b/tests/host_tools/cargo_build.py index 54302901211..56af399dea7 100644 --- a/tests/host_tools/cargo_build.py +++ b/tests/host_tools/cargo_build.py @@ -7,7 +7,7 @@ from pathlib import Path from framework import defs, utils -from framework.defs import FC_WORKSPACE_DIR +from framework.defs import DEFAULT_BINARY_DIR from framework.with_filelock import with_filelock DEFAULT_TARGET = f"{platform.machine()}-unknown-linux-musl" @@ -56,12 +56,11 @@ def cargo_test(path, extra_args=""): cargo("test", extra_args + " --all --no-fail-fast", env=env) -def get_binary(name, *, workspace_dir=FC_WORKSPACE_DIR, example=None): +def get_binary(name, *, binary_dir=DEFAULT_BINARY_DIR, example=None): """Get a binary. The binaries are built before starting a testrun.""" - target_dir = workspace_dir / "build" / "cargo_target" / DEFAULT_TARGET_DIR - bin_path = target_dir / name + bin_path = binary_dir / name if example: - bin_path = target_dir / "examples" / example + bin_path = binary_dir / "examples" / example return bin_path From 87ed2b3f0aab40d9027865d04535626bb1e0cdc4 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 12:54:51 +0000 Subject: [PATCH 286/464] test: pass through kwargs from uffd_handler() to get_example() To allow specifying a different directory in which to look for the uffd example binaries, so that they can be used in A/B-tests. Signed-off-by: Patrick Roy --- tests/framework/utils_uffd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py index 690eb423573..7715a5c2157 100644 --- a/tests/framework/utils_uffd.py +++ b/tests/framework/utils_uffd.py @@ -93,6 +93,6 @@ def spawn_pf_handler(vm, handler_path, mem_path): return uffd_handler -def uffd_handler(handler_name): +def uffd_handler(handler_name, **kwargs): """Retrieves the uffd handler with the given name""" - return cargo_build.get_example(f"uffd_{handler_name}_handler") + return cargo_build.get_example(f"uffd_{handler_name}_handler", **kwargs) From ed4ed9365ec282dfb5bcdf84d368eeacd2d2f1ff Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 12:52:28 +0000 Subject: [PATCH 287/464] devtool: also copy example binaries when doing build --rev Also copy the example binaries into the target directory when building some arbitrary revision (for example for A/B-tests). Signed-off-by: Patrick Roy --- tools/devtool | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 7bf8d4ad6fb..5f495b838c1 100755 --- a/tools/devtool +++ b/tools/devtool @@ -517,8 +517,9 @@ cmd_build() { if [ ! -z "$revision" ]; then popd git branch -D $branch_name - mkdir -p build/"$revision" + mkdir -p build/"$revision"/examples cp $tmp_dir/build/cargo_target/$(uname -m)-unknown-linux-$libc/$profile/* build/"$revision" + cp $tmp_dir/build/cargo_target/$(uname -m)-unknown-linux-$libc/$profile/examples/* build/"$revision"/examples cmd_sh "rm -rf $tmp_dir" fi From aea9a2e7eb0a79ef75019c8be562779afc084fec Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 15:55:44 +0000 Subject: [PATCH 288/464] fix(test): stop passing guest kernel when building vms from snapshot When building a microvm from a snapshot, there is no need to specify a guest kernel. Remove the parameter from SnapshotRestoreTest.sample_latency. Signed-off-by: Patrick Roy --- tests/integration_tests/performance/test_snapshot_ab.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 23224de6b31..c718b43f920 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -76,15 +76,12 @@ def configure_vm( return vm - def sample_latency( - self, microvm_factory, snapshot, guest_kernel_linux_5_10 - ) -> List[float]: + def sample_latency(self, microvm_factory, snapshot) -> List[float]: """Collects latency samples for the microvm configuration specified by this instance""" values = [] for _ in range(ITERATIONS): microvm = microvm_factory.build( - kernel=guest_kernel_linux_5_10, monitor_memory=False, ) microvm.spawn(emit_metrics=True) @@ -154,7 +151,6 @@ def test_restore_latency( samples = test_setup.sample_latency( microvm_factory, snapshot, - guest_kernel_linux_5_10, ) for sample in samples: From 190c06a76fd5088046008dd292bf96273d63051d Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:39:29 +0000 Subject: [PATCH 289/464] test_snapshot_ab: rename guest_kernel_acpi to guest_kernel This was the result of a find and replace gone awry it seems. Signed-off-by: Patrick Roy --- tests/integration_tests/performance/test_snapshot_ab.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index c718b43f920..4b09db126e4 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -43,12 +43,12 @@ def id(self): def configure_vm( self, microvm_factory, - guest_kernel_acpi, + guest_kernel, rootfs, ) -> Microvm: """Creates the initial snapshot that will be loaded repeatedly to sample latencies""" vm = microvm_factory.build( - guest_kernel_acpi, + guest_kernel, rootfs, monitor_memory=False, ) From 0781a3cf7b1ef4dbe893113c54bacce2f42a06cb Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 09:02:03 +0000 Subject: [PATCH 290/464] test: store uffd handler in microvm attribute So that we can later refer to it in tests, for example to parse its logs. Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 1 + tests/framework/utils_uffd.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 85ed588b809..8d87d137018 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -201,6 +201,7 @@ def __init__( self.ssh_key = None self.initrd_file = None self.boot_args = None + self.uffd_handler = None self.fc_binary_path = Path(fc_binary_path) assert fc_binary_path.exists() diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py index 7715a5c2157..a502003ff5f 100644 --- a/tests/framework/utils_uffd.py +++ b/tests/framework/utils_uffd.py @@ -89,6 +89,7 @@ def spawn_pf_handler(vm, handler_path, mem_path): handler_name, SOCKET_PATH, jailed_mem, vm.chroot(), "uffd.log" ) uffd_handler.spawn(vm.jailer.uid, vm.jailer.gid) + vm.uffd_handler = uffd_handler return uffd_handler From 271d8a8da9b185014fbb1718b1df7b63120c06e4 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:17:58 +0000 Subject: [PATCH 291/464] test: Add MicroVMFactory.build_n_from_snapshot Add a utility function that allows building multiple microvms from the same snapshot sequentially. Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 8d87d137018..7d2e9002822 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -38,6 +38,7 @@ from framework.microvm_helpers import MicrovmHelpers from framework.properties import global_props from framework.utils_drive import VhostUserBlkBackend, VhostUserBlkBackendType +from framework.utils_uffd import spawn_pf_handler, uffd_handler from host_tools.fcmetrics import FCMetricsMonitor from host_tools.memory import MemoryMonitor @@ -1128,6 +1129,52 @@ def build_from_snapshot(self, snapshot: Snapshot): vm.restore_from_snapshot(snapshot, resume=True) return vm + def build_n_from_snapshot( + self, + snapshot, + nr_vms, + *, + uffd_handler_name=None, + incremental=False, + use_snapshot_editor=True, + ): + """A generator of `n` microvms restored, either all restored from the same given snapshot + (incremental=False), or created by taking successive snapshots of restored VMs + """ + for _ in range(nr_vms): + microvm = self.build() + microvm.spawn() + + uffd_path = None + if uffd_handler_name is not None: + pf_handler = spawn_pf_handler( + microvm, + uffd_handler(uffd_handler_name, binary_dir=self.binary_path), + snapshot.mem, + ) + uffd_path = pf_handler.socket_path + + snapshot_copy = microvm.restore_from_snapshot( + snapshot, resume=True, uffd_path=uffd_path + ) + + yield microvm + + if incremental: + new_snapshot = microvm.make_snapshot(snapshot.snapshot_type) + + if snapshot.is_diff: + new_snapshot = new_snapshot.rebase_snapshot( + snapshot, use_snapshot_editor + ) + + snapshot = new_snapshot + + microvm.kill() + snapshot_copy.delete() + + snapshot.delete() + def kill(self): """Clean up all built VMs""" for vm in self.vms: From 294841e3b1576a61ccad72cdb08301740a6f9750 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:27:32 +0000 Subject: [PATCH 292/464] test: use build_n_from_snapshot to replace explicit loops Replace snapshot creation loops in test_5_snapshots, test_vmgenid and test_restore_latency with calls to build_n_from_snapshot Signed-off-by: Patrick Roy --- .../functional/test_snapshot_basic.py | 44 +++---------------- .../performance/test_snapshot_ab.py | 11 +---- 2 files changed, 7 insertions(+), 48 deletions(-) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 6fe41f4d5a6..09e14b92448 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -149,12 +149,9 @@ def test_5_snapshots( snapshot = vm.make_snapshot(snapshot_type) vm.kill() - for i in range(seq_len): - logger.info("Load snapshot #%s, mem %s", i, snapshot.mem) - microvm = microvm_factory.build() - microvm.spawn() - copied_snapshot = microvm.restore_from_snapshot(snapshot, resume=True) - + for microvm in microvm_factory.build_n_from_snapshot( + snapshot, seq_len, incremental=True, use_snapshot_editor=use_snapshot_editor + ): # FIXME: This and the sleep below reduce the rate of vsock/ssh connection # related spurious test failures, although we do not know why this is the case. time.sleep(2) @@ -171,21 +168,6 @@ def test_5_snapshots( check_filesystem(microvm.ssh, "squashfs", "/dev/vda") time.sleep(2) - logger.info("Create snapshot %s #%d.", snapshot_type, i + 1) - new_snapshot = microvm.make_snapshot(snapshot_type) - - # If we are testing incremental snapshots we must merge the base with - # current layer. - if snapshot.is_diff: - logger.info("Base: %s, Layer: %s", snapshot.mem, new_snapshot.mem) - new_snapshot = new_snapshot.rebase_snapshot( - snapshot, use_snapshot_editor=use_snapshot_editor - ) - - microvm.kill() - copied_snapshot.delete() - # Update the base for next iteration. - snapshot = new_snapshot def test_patch_drive_snapshot(uvm_nano, microvm_factory): @@ -524,27 +506,13 @@ def test_vmgenid(guest_kernel_linux_6_1, rootfs, microvm_factory, snapshot_type) base_snapshot = snapshot base_vm.kill() - for i in range(5): - vm = microvm_factory.build() - vm.spawn() - copied_snapshot = vm.restore_from_snapshot(snapshot, resume=True) - + for i, vm in enumerate( + microvm_factory.build_n_from_snapshot(base_snapshot, 5, incremental=True) + ): # We should have as DMESG_VMGENID_RESUME messages as # snapshots we have resumed check_vmgenid_update_count(vm, i + 1) - snapshot = vm.make_snapshot(snapshot_type) - vm.kill() - copied_snapshot.delete() - - # If we are testing incremental snapshots we ust merge the base with - # current layer. - if snapshot.is_diff: - snapshot = snapshot.rebase_snapshot(base_snapshot) - - # Update the base for next iteration - base_snapshot = snapshot - # TODO add `global_props.host_os == "amzn2"` condition # once amazon linux kernels have patches. diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 4b09db126e4..b91feb03f80 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -80,13 +80,7 @@ def sample_latency(self, microvm_factory, snapshot) -> List[float]: """Collects latency samples for the microvm configuration specified by this instance""" values = [] - for _ in range(ITERATIONS): - microvm = microvm_factory.build( - monitor_memory=False, - ) - microvm.spawn(emit_metrics=True) - snapshot_copy = microvm.restore_from_snapshot(snapshot, resume=True) - + for microvm in microvm_factory.build_n_from_snapshot(snapshot, ITERATIONS): value = 0 # Parse all metric data points in search of load_snapshot time. microvm.flush_metrics() @@ -98,10 +92,7 @@ def sample_latency(self, microvm_factory, snapshot) -> List[float]: break assert value > 0 values.append(value) - microvm.kill() - snapshot_copy.delete() - snapshot.delete() return values From 31ee8512e50e7edb3d722be556926e0f24fd19c3 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:29:43 +0000 Subject: [PATCH 293/464] test_snapshot_ab: move metrics dimension setting into configure_vm Move the initialization of the metrics logger dimensions into `configure_vm`, as later on there will be multiple tests having to do exactly the same sequence of configure + setup metrics. Signed-off-by: Patrick Roy --- .../performance/test_snapshot_ab.py | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index b91feb03f80..5ad055a7495 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -40,12 +40,7 @@ def id(self): """Computes a unique id for this test instance""" return "all_dev" if self.all_devices else f"{self.vcpus}vcpu_{self.mem}mb" - def configure_vm( - self, - microvm_factory, - guest_kernel, - rootfs, - ) -> Microvm: + def configure_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: """Creates the initial snapshot that will be loaded repeatedly to sample latencies""" vm = microvm_factory.build( guest_kernel, @@ -74,6 +69,16 @@ def configure_vm( ) vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") + metrics.set_dimensions( + { + "net_devices": str(self.nets), + "block_devices": str(self.blocks), + "vsock_devices": str(int(self.all_devices)), + "balloon_devices": str(int(self.all_devices)), + **vm.dimensions, + } + ) + return vm def sample_latency(self, microvm_factory, snapshot) -> List[float]: @@ -122,23 +127,16 @@ def test_restore_latency( We only test a single guest kernel, as the guest kernel does not "participate" in snapshot restore. """ - vm = test_setup.configure_vm(microvm_factory, guest_kernel_linux_5_10, rootfs) - vm.start() - - metrics.set_dimensions( - { - "performance_test": "test_restore_latency", - "net_devices": str(test_setup.nets), - "block_devices": str(test_setup.blocks), - "vsock_devices": str(int(test_setup.all_devices)), - "balloon_devices": str(int(test_setup.all_devices)), - **vm.dimensions, - } + vm = test_setup.configure_vm( + microvm_factory, guest_kernel_linux_5_10, rootfs, metrics ) + vm.start() snapshot = vm.snapshot_full() vm.kill() + metrics.put_dimensions({"performance_test": "test_restore_latency"}) + samples = test_setup.sample_latency( microvm_factory, snapshot, From 137d413367c17b19dbbb5d4b88815bcfa2f62334 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:31:02 +0000 Subject: [PATCH 294/464] test_snapshot_ab: start VM inside configure_vm No need to defer the starting. Also rename it to `boot_vm` to more accurately reflect what it does now. Signed-off-by: Patrick Roy --- tests/integration_tests/performance/test_snapshot_ab.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 5ad055a7495..189e58b25b1 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -40,7 +40,7 @@ def id(self): """Computes a unique id for this test instance""" return "all_dev" if self.all_devices else f"{self.vcpus}vcpu_{self.mem}mb" - def configure_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: + def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: """Creates the initial snapshot that will be loaded repeatedly to sample latencies""" vm = microvm_factory.build( guest_kernel, @@ -78,6 +78,7 @@ def configure_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microv **vm.dimensions, } ) + vm.start() return vm @@ -127,10 +128,7 @@ def test_restore_latency( We only test a single guest kernel, as the guest kernel does not "participate" in snapshot restore. """ - vm = test_setup.configure_vm( - microvm_factory, guest_kernel_linux_5_10, rootfs, metrics - ) - vm.start() + vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) snapshot = vm.snapshot_full() vm.kill() From 8c20fd15030a5de957eda1c597cd3920c0d4f62a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 3 Mar 2025 16:32:11 +0000 Subject: [PATCH 295/464] test_snapshot_ab: open code sample_latency This function only has one possible call-site, and that's test_restore_latency. Inlining it into its call site makes things a bit simpler (no need for a temporary array). Signed-off-by: Patrick Roy --- .../performance/test_snapshot_ab.py | 38 ++++++------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 189e58b25b1..5caa87bb17f 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -4,7 +4,6 @@ import tempfile from dataclasses import dataclass from functools import lru_cache -from typing import List import pytest @@ -82,25 +81,6 @@ def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: return vm - def sample_latency(self, microvm_factory, snapshot) -> List[float]: - """Collects latency samples for the microvm configuration specified by this instance""" - values = [] - - for microvm in microvm_factory.build_n_from_snapshot(snapshot, ITERATIONS): - value = 0 - # Parse all metric data points in search of load_snapshot time. - microvm.flush_metrics() - metrics = microvm.get_all_metrics() - for data_point in metrics: - cur_value = data_point["latencies_us"]["load_snapshot"] - if cur_value > 0: - value = cur_value / USEC_IN_MSEC - break - assert value > 0 - values.append(value) - - return values - @pytest.mark.nonci @pytest.mark.parametrize( @@ -135,10 +115,14 @@ def test_restore_latency( metrics.put_dimensions({"performance_test": "test_restore_latency"}) - samples = test_setup.sample_latency( - microvm_factory, - snapshot, - ) - - for sample in samples: - metrics.put_metric("latency", sample, "Milliseconds") + for microvm in microvm_factory.build_n_from_snapshot(snapshot, ITERATIONS): + value = 0 + # Parse all metric data points in search of load_snapshot time. + microvm.flush_metrics() + for data_point in microvm.get_all_metrics(): + cur_value = data_point["latencies_us"]["load_snapshot"] + if cur_value > 0: + value = cur_value / USEC_IN_MSEC + break + assert value > 0 + metrics.put_metric("latency", value, "Milliseconds") From 93467bdc600f497253e9265d00e27345797b2d88 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Feb 2025 16:59:10 +0000 Subject: [PATCH 296/464] test: add post-restore latency test Add a snapshot latency test that output metrics on how long it takes to memset a 128MB memory region post-snapshot restore. We only collect these latencies for a single configuration (1024MB, 2vCPU), since they will be the same no matter the size of the memory. Run with an on-demand uffd handler and compare to mmap-ing the snapshot file as a baseline. Also use the fault_all handler, which will allow us to measure latencies due to "fast" page faults, e.g. those that are just for setting up stage-2 page able entries but where otherwise memory is already faulted into userspace. Signed-off-by: Patrick Roy --- .../performance/test_snapshot_ab.py | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 5caa87bb17f..9133eb9d4de 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -1,7 +1,9 @@ # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """Performance benchmark for snapshot restore.""" +import signal import tempfile +import time from dataclasses import dataclass from functools import lru_cache @@ -11,6 +13,7 @@ from framework.microvm import Microvm USEC_IN_MSEC = 1000 +NS_IN_MSEC = 1_000_000 ITERATIONS = 30 @@ -113,7 +116,9 @@ def test_restore_latency( snapshot = vm.snapshot_full() vm.kill() - metrics.put_dimensions({"performance_test": "test_restore_latency"}) + metrics.put_dimensions( + {"performance_test": "test_restore_latency", "uffd_handler": "None"} + ) for microvm in microvm_factory.build_n_from_snapshot(snapshot, ITERATIONS): value = 0 @@ -126,3 +131,46 @@ def test_restore_latency( break assert value > 0 metrics.put_metric("latency", value, "Milliseconds") + + +# When using the fault-all handler, all guest memory will be faulted in way before the helper tool +# wakes up, because it gets faulted in on the first page fault. In this scenario, we are not measuring UFFD +# latencies, but KVM latencies of setting up missing EPT entries. +@pytest.mark.nonci +@pytest.mark.parametrize("uffd_handler", [None, "valid", "fault_all"]) +def test_post_restore_latency( + microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler +): + """Collects latency metric of post-restore memory accesses done inside the guest""" + test_setup = SnapshotRestoreTest(mem=1024, vcpus=2) + vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) + + vm.ssh.check_output( + "nohup /usr/local/bin/fast_page_fault_helper >/dev/null 2>&1 Date: Tue, 4 Mar 2025 08:32:36 +0000 Subject: [PATCH 297/464] test: Also emit post-restore latency metrics for huge pages Runs the new test_post_restore_latency test also for hugepages-backed VMs Signed-off-by: Patrick Roy --- .../performance/test_snapshot_ab.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 9133eb9d4de..70d0ed6adc2 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -10,7 +10,7 @@ import pytest import host_tools.drive as drive_tools -from framework.microvm import Microvm +from framework.microvm import HugePagesConfig, Microvm USEC_IN_MSEC = 1000 NS_IN_MSEC = 1_000_000 @@ -36,6 +36,7 @@ class SnapshotRestoreTest: nets: int = 3 blocks: int = 3 all_devices: bool = False + huge_pages: HugePagesConfig = HugePagesConfig.NONE @property def id(self): @@ -55,6 +56,7 @@ def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: vcpu_count=self.vcpus, mem_size_mib=self.mem, rootfs_io_engine="Sync", + huge_pages=self.huge_pages, ) for _ in range(self.nets): @@ -77,6 +79,7 @@ def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: "block_devices": str(self.blocks), "vsock_devices": str(int(self.all_devices)), "balloon_devices": str(int(self.all_devices)), + "huge_pages_config": str(self.huge_pages), **vm.dimensions, } ) @@ -138,11 +141,15 @@ def test_restore_latency( # latencies, but KVM latencies of setting up missing EPT entries. @pytest.mark.nonci @pytest.mark.parametrize("uffd_handler", [None, "valid", "fault_all"]) +@pytest.mark.parametrize("huge_pages", HugePagesConfig) def test_post_restore_latency( - microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler + microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler, huge_pages ): """Collects latency metric of post-restore memory accesses done inside the guest""" - test_setup = SnapshotRestoreTest(mem=1024, vcpus=2) + if huge_pages != HugePagesConfig.NONE and uffd_handler is None: + pytest.skip("huge page snapshots can only be restored using uffd") + + test_setup = SnapshotRestoreTest(mem=1024, vcpus=2, huge_pages=huge_pages) vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) vm.ssh.check_output( From e3e8769ad565a4f76a80c0e790bbdfd9c85e5ec8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 08:56:28 +0000 Subject: [PATCH 298/464] test: Add post-restore population latency test While the post_restore_latency test measures the time on-demand faulting takes from the guest's perspective, this test measures the actual time it takes to fault in guest memory. We cannot collect this data by simply using the fault_all handler in the post-restore test, because the handler will get triggered way before the fast_page_fault_helper script continues running (because the first page fault will be triggered by sshd or the kernel, so by the time out helper runs, the uffd handler will already be done and we won't notice any latency). Therefore, have the fault_all handler print the time it took to populate all of guest memory to its log file, and parse this number. Signed-off-by: Patrick Roy --- .../examples/uffd/fault_all_handler.rs | 5 +++ .../performance/test_snapshot_ab.py | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/firecracker/examples/uffd/fault_all_handler.rs b/src/firecracker/examples/uffd/fault_all_handler.rs index d0f127a8ce1..6711350497a 100644 --- a/src/firecracker/examples/uffd/fault_all_handler.rs +++ b/src/firecracker/examples/uffd/fault_all_handler.rs @@ -11,6 +11,7 @@ use std::fs::File; use std::os::unix::net::UnixListener; use uffd_utils::{Runtime, UffdHandler}; +use utils::time::{get_time_us, ClockType}; fn main() { let mut args = std::env::args(); @@ -34,9 +35,13 @@ fn main() { match event { userfaultfd::Event::Pagefault { .. } => { + let start = get_time_us(ClockType::Monotonic); for region in uffd_handler.mem_regions.clone() { uffd_handler.serve_pf(region.base_host_virt_addr as _, region.size); } + let end = get_time_us(ClockType::Monotonic); + + println!("Finished Faulting All: {}us", end - start); } _ => panic!("Unexpected event on userfaultfd"), } diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 70d0ed6adc2..7e20befcc27 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -1,6 +1,7 @@ # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """Performance benchmark for snapshot restore.""" +import re import signal import tempfile import time @@ -181,3 +182,42 @@ def test_post_restore_latency( ) metrics.put_metric("fault_latency", int(duration) / NS_IN_MSEC, "Milliseconds") + + +@pytest.mark.nonci +@pytest.mark.parametrize("huge_pages", HugePagesConfig) +def test_population_latency( + microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, huge_pages +): + """Collects population latency metrics (e.g. how long it takes UFFD handler to fault in all memory)""" + test_setup = SnapshotRestoreTest(mem=128, vcpus=1, huge_pages=huge_pages) + vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) + snapshot = vm.snapshot_full() + vm.kill() + + metrics.put_dimensions( + {"performance_test": "test_population_latency", "uffd_handler": "fault_all"} + ) + + for microvm in microvm_factory.build_n_from_snapshot( + snapshot, ITERATIONS, uffd_handler_name="fault_all" + ): + # do _something_ to trigger a pagefault, which will then cause the UFFD handler to fault in _everything_ + microvm.ssh.check_output("true") + + for _ in range(5): + time.sleep(1) + + match = re.match( + r"Finished Faulting All: (\d+)us", microvm.uffd_handler.log_data + ) + + if match: + latency_us = int(match.group(1)) + + metrics.put_metric( + "populate_latency", latency_us / 1000, "Milliseconds" + ) + break + else: + raise RuntimeError("UFFD handler did not print population latency after 5s") From 1461e280e0838a85a8afc91814037294d5cc770b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 13:42:55 +0000 Subject: [PATCH 299/464] fix(ab): its dict.keys(), not dict.key() We were calling a non-existing function on an error path. This is why I prefer compiled languages smh. Signed-off-by: Patrick Roy --- tools/ab_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ab_test.py b/tools/ab_test.py index 7349adcb862..b296627ba31 100755 --- a/tools/ab_test.py +++ b/tools/ab_test.py @@ -136,7 +136,7 @@ def load_data_series(report_path: Path, tag=None, *, reemit: bool = False): # multiple EMF log messages. We need to reassemble :( assert ( processed_emf[dimension_set].keys() == result.keys() - ), f"Found incompatible metrics associated with dimension set {dimension_set}: {processed_emf[dimension_set].key()} in one EMF message, but {result.keys()} in another." + ), f"Found incompatible metrics associated with dimension set {dimension_set}: {processed_emf[dimension_set].keys()} in one EMF message, but {result.keys()} in another." for metric, (values, unit) in processed_emf[dimension_set].items(): assert result[metric][1] == unit From fbd0aa1240a0257e9d1b1280ced50cb13b2acd31 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 4 Mar 2025 14:22:03 +0000 Subject: [PATCH 300/464] test(ab): allow dimensions to be split into multiple lists When using metrics.put_dimensions from python code, then the resulting EMF messages will have a list of lists in their "Dimensions" key. Currently, ab_test.py assumes that this list of lists always has length one, meaning it ignores additional dimensions added via put_dimensions. Have it instead flatten the list of lists so that it always considers all dimensions. Signed-off-by: Patrick Roy --- tools/ab_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/ab_test.py b/tools/ab_test.py index b296627ba31..7c4cdcada7a 100755 --- a/tools/ab_test.py +++ b/tools/ab_test.py @@ -64,7 +64,11 @@ def extract_dimensions(emf): # Skipped tests emit a duration metric, but have no dimensions set return {} - dimension_list = emf["_aws"]["CloudWatchMetrics"][0]["Dimensions"][0] + dimension_list = [ + dim + for dimensions in emf["_aws"]["CloudWatchMetrics"][0]["Dimensions"] + for dim in dimensions + ] return {key: emf[key] for key in emf if key in dimension_list} From 2f8228f16f29da63efc4935d1e927882e47f7087 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 6 Mar 2025 12:33:21 +0000 Subject: [PATCH 301/464] refactor: rename uffd_valid_handler to uffd_on_demand_handler This better describes what the handler actually does (technically, fault_all_handler is also "valid"), and now that some tests emit the name of the uffd handler as a metric, the names should be descriptive from the get-go to avoid confusion and future renamings. Signed-off-by: Patrick Roy --- docs/snapshotting/handling-page-faults-on-snapshot-resume.md | 2 +- src/firecracker/Cargo.toml | 4 ++-- .../examples/uffd/{valid_handler.rs => on_demand_handler.rs} | 0 tests/integration_tests/functional/test_uffd.py | 2 +- tests/integration_tests/performance/test_huge_pages.py | 4 ++-- tests/integration_tests/performance/test_snapshot_ab.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) rename src/firecracker/examples/uffd/{valid_handler.rs => on_demand_handler.rs} (100%) diff --git a/docs/snapshotting/handling-page-faults-on-snapshot-resume.md b/docs/snapshotting/handling-page-faults-on-snapshot-resume.md index ea790624a18..a5da980124e 100644 --- a/docs/snapshotting/handling-page-faults-on-snapshot-resume.md +++ b/docs/snapshotting/handling-page-faults-on-snapshot-resume.md @@ -162,7 +162,7 @@ connect/send data. ### Example An example of a handler process can be found -[here](../../src/firecracker/examples/uffd/valid_handler.rs). The process is +[here](../../src/firecracker/examples/uffd/on_demand_handler.rs). The process is designed to tackle faults on a certain address by loading into memory the entire region that the address belongs to, but users can choose any other behavior that suits their use case best. diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 29778af061d..40b2795050d 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -57,8 +57,8 @@ name = "uffd_malicious_handler" path = "examples/uffd/malicious_handler.rs" [[example]] -name = "uffd_valid_handler" -path = "examples/uffd/valid_handler.rs" +name = "uffd_on_demand_handler" +path = "examples/uffd/on_demand_handler.rs" [[example]] name = "uffd_fault_all_handler" diff --git a/src/firecracker/examples/uffd/valid_handler.rs b/src/firecracker/examples/uffd/on_demand_handler.rs similarity index 100% rename from src/firecracker/examples/uffd/valid_handler.rs rename to src/firecracker/examples/uffd/on_demand_handler.rs diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index 35b03d7aa34..95819844f05 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -92,7 +92,7 @@ def test_valid_handler(uvm_plain, snapshot): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot.mem) vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index acfee58139d..5839245ebd9 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -93,7 +93,7 @@ def test_hugetlbfs_snapshot(microvm_factory, guest_kernel_linux_5_10, rootfs): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot.mem) vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) @@ -135,7 +135,7 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("valid"), snapshot_merged.mem) + pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot_merged.mem) vm.restore_from_snapshot( snapshot_merged, resume=True, uffd_path=pf_handler.socket_path diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 7e20befcc27..655566dcb13 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -141,7 +141,7 @@ def test_restore_latency( # wakes up, because it gets faulted in on the first page fault. In this scenario, we are not measuring UFFD # latencies, but KVM latencies of setting up missing EPT entries. @pytest.mark.nonci -@pytest.mark.parametrize("uffd_handler", [None, "valid", "fault_all"]) +@pytest.mark.parametrize("uffd_handler", [None, "on_demand", "fault_all"]) @pytest.mark.parametrize("huge_pages", HugePagesConfig) def test_post_restore_latency( microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler, huge_pages From fbb230aa1784fe01d4891f1bb32e5f830d8c34f2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 6 Mar 2025 13:17:50 +0000 Subject: [PATCH 302/464] test: avoid memsetting in favor of just touching one byte per page To bring down the overhead of the testing script, only touch a single byte on each page (as that's enough to fault in the entire page), instead of memsetting everything. Signed-off-by: Patrick Roy --- .../overlay/usr/local/bin/fast_page_fault_helper.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/resources/overlay/usr/local/bin/fast_page_fault_helper.c b/resources/overlay/usr/local/bin/fast_page_fault_helper.c index 96e565f0c3f..7558f7b09fc 100644 --- a/resources/overlay/usr/local/bin/fast_page_fault_helper.c +++ b/resources/overlay/usr/local/bin/fast_page_fault_helper.c @@ -19,6 +19,14 @@ #define MEM_SIZE_MIB (128 * 1024 * 1024) #define NANOS_PER_SEC 1000000000 +#define PAGE_SIZE 4096 + +void touch_memory(void *mem, size_t size, char val) { + void *end = mem + size; + for (; mem < end; mem += PAGE_SIZE) { + *((char *)mem) = val; + } +} int main() { sigset_t set; @@ -45,12 +53,12 @@ int main() { return 1; } - memset(ptr, 1, MEM_SIZE_MIB); + touch_memory(ptr, MEM_SIZE_MIB, 1); sigwait(&set, &signal); clock_gettime(CLOCK_BOOTTIME, &start); - memset(ptr, 2, MEM_SIZE_MIB); + touch_memory(ptr, MEM_SIZE_MIB, 2); clock_gettime(CLOCK_BOOTTIME, &end); duration_nanos = (end.tv_sec - start.tv_sec) * NANOS_PER_SEC + end.tv_nsec - start.tv_nsec; From 333bc2de6bf6cd79e4721c1324066798b3ddaf1e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 6 Mar 2025 16:35:12 +0000 Subject: [PATCH 303/464] fix: allocate more huge pages for performance tests On m6a/6.1, post_populate with fault_all handler and 2M pages fails because of the UFFD handler panicking during faulting, returning `PartiallyCopied(1022MB)`. This is because we are depleting the huge pages pool. Thus, allocate some more. Admittedly, I do not understand why thisd only happens on m6a/6.1. Signed-off-by: Patrick Roy --- tools/devtool | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/devtool b/tools/devtool index 5f495b838c1..35794256138 100755 --- a/tools/devtool +++ b/tools/devtool @@ -743,9 +743,9 @@ cmd_test() { # It seems that even if the tests using huge pages run sequentially on ag=1 agents, right-sizing the huge pages # pool to the total number of huge pages used across all tests results in spurious failures with pool depletion # anyway (something else on the host seems to be stealing our huge pages, and we cannot "ear mark" them for - # Firecracker processes). Thus, just allocate 4GB of them and call it a day. + # Firecracker processes). Thus, just allocate 8GB of them and call it a day. say "Setting up huge pages pool" - num_hugetlbfs_pages=2048 + num_hugetlbfs_pages=4096 huge_pages_old=$(cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) huge_pages_new=$(echo $num_hugetlbfs_pages |sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) From 2c74c653021d388b36501e545eda3296c6cbabde Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 10 Mar 2025 11:58:44 +0000 Subject: [PATCH 304/464] chore(aarch64): increase the max_value for timer reset test The counter value observed in tests sometimes is a bit larger than 1000 cycles. Adjust max_value to accommodate this. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/vcpu.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 7b34ae91896..d46b9b56720 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -271,8 +271,9 @@ mod tests { // We are reading the SYS_CNTPCT_EL0 right after resetting it. // If reset did happen successfully, the value should be quite small when we read it. // If the reset did not happen, the value will be same as on the host and it surely - // will be more that MAX_VALUE. - let max_value = 1000; + // will be more that `max_value`. Measurements show that usually value is close + // to 1000. Use bigger `max_value` just in case. + let max_value = 10_000; assert!(counter_value < max_value); } From c9c90ecc4589bc913164433ad9af2fe8143be740 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Feb 2025 12:54:57 +0000 Subject: [PATCH 305/464] fix(test): actually assert error msg in test_api_mmds_config Make the test actually assert that the returned error matches the error message stored in a local variable. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 369ae659877..b201ed9a2f9 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -253,7 +253,7 @@ def test_api_mmds_config(uvm_plain): "The list of network interface IDs that allow " "forwarding MMDS requests is empty." ) - with pytest.raises(RuntimeError): + with pytest.raises(RuntimeError, match=err_msg): test_microvm.api.mmds_config.put(network_interfaces=[]) # Setting MMDS config when no network device has been attached From a65704452bdb23e8864e82d1415382ca2b8ba87b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Feb 2025 12:56:37 +0000 Subject: [PATCH 306/464] test: eliminate unused variable from test_api_put_update_pre_boot The `response` variable was assigned, but never used. Just delete it. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index b201ed9a2f9..ec8256482ac 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -104,7 +104,7 @@ def test_api_put_update_pre_boot(uvm_plain, io_engine): test_microvm.basic_config() fs1 = drive_tools.FilesystemFile(os.path.join(test_microvm.fsfiles, "scratch")) - response = test_microvm.api.drive.put( + test_microvm.api.drive.put( drive_id="scratch", path_on_host=test_microvm.create_jailed_resource(fs1.path), is_root_device=False, From d145cddc9917705d8b51fee408d0dacca71e6aa5 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Feb 2025 13:21:14 +0000 Subject: [PATCH 307/464] fix(test): Fix io_engine related tests Ensure all io_engine related tests run with both the sync and the async io_engine. Prior to 4.14 deprecation, some tests used the following logic to determine whether the Async engine or the Sync engine should be tested: If io_uring is supported (e.g. host_kernel != 4.14) then use Async Else use Sync This meant we were running with the Async engine on 5.10 and 6.1, and with the Sync engine on 4.14. However, once 4.14 went out of support, this meant that tests employing this logic only ever tested the Async engine anymore. Fix this by having all these tests always run with both Sync and Async engines, independently of host kernel version. Also remove all logic around checking whether io_uring is supported, because it definitely is supported on all currently supported host kernels. Signed-off-by: Patrick Roy --- tests/conftest.py | 2 - tests/framework/defs.py | 4 -- tests/framework/utils.py | 13 ------- .../integration_tests/functional/test_api.py | 37 ++++++------------- 4 files changed, 11 insertions(+), 45 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fb0b88b677a..3b75a3fa596 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -373,8 +373,6 @@ def cpu_template_any(request, record_property): @pytest.fixture(params=["Sync", "Async"]) def io_engine(request): """All supported io_engines""" - if request.param == "Async" and not utils.is_io_uring_supported(): - pytest.skip("io_uring not supported in this kernel") return request.param diff --git a/tests/framework/defs.py b/tests/framework/defs.py index 38fbe6802df..aec3568a85d 100644 --- a/tests/framework/defs.py +++ b/tests/framework/defs.py @@ -33,10 +33,6 @@ / "release" ) -# The minimum required host kernel version for which io_uring is supported in -# Firecracker. -MIN_KERNEL_VERSION_FOR_IO_URING = "5.10.51" - SUPPORTED_HOST_KERNELS = ["5.10", "6.1"] IMG_DIR = Path(DEFAULT_TEST_SESSION_ROOT_PATH) / "img" diff --git a/tests/framework/utils.py b/tests/framework/utils.py index d7ecb00c7cd..19f31cf71b0 100644 --- a/tests/framework/utils.py +++ b/tests/framework/utils.py @@ -28,8 +28,6 @@ wait_fixed, ) -from framework.defs import MIN_KERNEL_VERSION_FOR_IO_URING - FLUSH_CMD = 'screen -S {session} -X colon "logfile flush 0^M"' CommandReturn = namedtuple("CommandReturn", "returncode stdout stderr") CMDLOG = logging.getLogger("commands") @@ -455,17 +453,6 @@ def get_kernel_version(level=2): return linux_version -def is_io_uring_supported(): - """ - Return whether Firecracker supports io_uring for the running kernel ... - - ...version. - """ - kv = packaging.version.parse(get_kernel_version()) - min_kv = packaging.version.parse(MIN_KERNEL_VERSION_FOR_IO_URING) - return kv >= min_kv - - def generate_mmds_session_token(ssh_connection, ipv4_address, token_ttl): """Generate session token used for MMDS V2 requests.""" cmd = "curl -m 2 -s" diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index ec8256482ac..e0212a49f77 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -17,7 +17,7 @@ import host_tools.drive as drive_tools import host_tools.network as net_tools from framework import utils, utils_cpuid -from framework.utils import get_firecracker_version_from_toml, is_io_uring_supported +from framework.utils import get_firecracker_version_from_toml MEM_LIMIT = 1000000000 @@ -46,7 +46,7 @@ def test_api_happy_start(uvm_plain): assert "Kernel loaded using PVH boot protocol" in test_microvm.log_data -def test_drive_io_engine(uvm_plain): +def test_drive_io_engine(uvm_plain, io_engine): """ Test io_engine configuration. @@ -59,8 +59,6 @@ def test_drive_io_engine(uvm_plain): test_microvm.basic_config(add_root_device=False) test_microvm.add_net_iface() - supports_io_uring = is_io_uring_supported() - kwargs = { "drive_id": "rootfs", "path_on_host": test_microvm.create_jailed_resource(test_microvm.rootfs_file), @@ -68,26 +66,13 @@ def test_drive_io_engine(uvm_plain): "is_read_only": True, } - # Test the opposite of the default backend type. - if supports_io_uring: - test_microvm.api.drive.put(io_engine="Sync", **kwargs) - - if not supports_io_uring: - with pytest.raises(RuntimeError): - test_microvm.api.drive.put(io_engine="Async", **kwargs) - # The Async engine is not supported for older kernels. - test_microvm.check_log_message( - "Received Error. Status code: 400 Bad Request. Message: Drive config error: " - "Unable to create the virtio block device: Virtio backend error: " - "Error coming from the IO engine: Unsupported engine type: Async" - ) - - # Now configure the default engine type and check that it works. - test_microvm.api.drive.put(**kwargs) + test_microvm.api.drive.put(io_engine=io_engine, **kwargs) test_microvm.start() - assert test_microvm.api.vm_config.get().json()["drives"][0]["io_engine"] == "Sync" + assert ( + test_microvm.api.vm_config.get().json()["drives"][0]["io_engine"] == io_engine + ) def test_api_put_update_pre_boot(uvm_plain, io_engine): @@ -735,7 +720,7 @@ def test_negative_api_patch_post_boot(uvm_plain, io_engine): test_microvm.api.logger.patch(level="Error") -def test_drive_patch(uvm_plain): +def test_drive_patch(uvm_plain, io_engine): """ Extensively test drive PATCH scenarios before and after boot. """ @@ -752,7 +737,7 @@ def test_drive_patch(uvm_plain): path_on_host=fs.path, is_root_device=False, is_read_only=False, - io_engine="Async" if is_io_uring_supported() else "Sync", + io_engine=io_engine, ) fs_vub = drive_tools.FilesystemFile( @@ -766,7 +751,7 @@ def test_drive_patch(uvm_plain): test_microvm.start() - _drive_patch(test_microvm) + _drive_patch(test_microvm, io_engine) @pytest.mark.skipif( @@ -802,7 +787,7 @@ def test_send_ctrl_alt_del(uvm_plain): pass -def _drive_patch(test_microvm): +def _drive_patch(test_microvm, io_engine): """Exercise drive patch test scenarios.""" # Patches without mandatory fields for virtio block are not allowed. expected_msg = "Unable to patch the block device: Device manager error: Running method expected different backend. Please verify the request arguments" @@ -912,7 +897,7 @@ def _drive_patch(test_microvm): "bandwidth": {"size": 5000, "one_time_burst": None, "refill_time": 100}, "ops": {"size": 500, "one_time_burst": None, "refill_time": 100}, }, - "io_engine": "Async" if is_io_uring_supported() else "Sync", + "io_engine": io_engine, "socket": None, }, { From 123a8da1fd51c8dd3a5af15e12a903714449dcbe Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Feb 2025 06:36:57 +0000 Subject: [PATCH 308/464] fix(test): Catch correct ConnectionError in test_deflate_on_oom Turns out that `except ConnectionError` catches the `ConnectionError` from the standard library, while what needs to be caught is the (different) `ConnectionError` from the `requests` package. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_balloon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py index f222c46aa0b..c483683b7bb 100644 --- a/tests/integration_tests/functional/test_balloon.py +++ b/tests/integration_tests/functional/test_balloon.py @@ -7,6 +7,7 @@ from subprocess import TimeoutExpired import pytest +import requests from tenacity import retry, stop_after_attempt, wait_fixed from framework.utils import check_output, get_free_mem_ssh @@ -209,7 +210,7 @@ def test_deflate_on_oom(uvm_plain_any, deflate_on_oom): try: balloon_size_after = test_microvm.api.balloon_stats.get().json()["actual_mib"] - except ConnectionError: + except requests.exceptions.ConnectionError: assert ( not deflate_on_oom ), "Guest died even though it should have deflated balloon to alleviate memory pressure" From ee477303dd22a7b6b61e807a8b29f1f5c55f93f0 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 7 Mar 2025 10:55:32 +0000 Subject: [PATCH 309/464] test: run test_ctrl_al_del with all guest kernels Use uvm_plain_any instead of uvm_plain, as the latter only uses 5.10 guest kernel, but this test actually has meaningful interactions with the guest kernel, so testing all kernels is valuable. Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index e0212a49f77..b21e86e0d60 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -757,13 +757,13 @@ def test_drive_patch(uvm_plain, io_engine): @pytest.mark.skipif( platform.machine() != "x86_64", reason="not yet implemented on aarch64" ) -def test_send_ctrl_alt_del(uvm_plain): +def test_send_ctrl_alt_del(uvm_plain_any): """ Test shutting down the microVM gracefully on x86, by sending CTRL+ALT+DEL. """ # This relies on the i8042 device and AT Keyboard support being present in # the guest kernel. - test_microvm = uvm_plain + test_microvm = uvm_plain_any test_microvm.spawn() test_microvm.basic_config() From db6d29b880a5130825946ff14fbd2499080df290 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 10 Mar 2025 15:43:09 +0000 Subject: [PATCH 310/464] fix: do not try to use put_dimensions to merge dimension sets That's apparently not how that function works. Instead, it just associates a completely separate dimension set with the metric-to-be-emitted, and then emits it twice (with different dimensions sets). Needless to say, that's not what we want, so go back to centrally configuring all metrics with a single call to set_dimensions. Fixes: 31ee8512e50e Signed-off-by: Patrick Roy --- .../performance/test_snapshot_ab.py | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 655566dcb13..6dc2d045a45 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -44,7 +44,7 @@ def id(self): """Computes a unique id for this test instance""" return "all_dev" if self.all_devices else f"{self.vcpus}vcpu_{self.mem}mb" - def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: + def boot_vm(self, microvm_factory, guest_kernel, rootfs) -> Microvm: """Creates the initial snapshot that will be loaded repeatedly to sample latencies""" vm = microvm_factory.build( guest_kernel, @@ -74,16 +74,6 @@ def boot_vm(self, microvm_factory, guest_kernel, rootfs, metrics) -> Microvm: ) vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock") - metrics.set_dimensions( - { - "net_devices": str(self.nets), - "block_devices": str(self.blocks), - "vsock_devices": str(int(self.all_devices)), - "balloon_devices": str(int(self.all_devices)), - "huge_pages_config": str(self.huge_pages), - **vm.dimensions, - } - ) vm.start() return vm @@ -115,15 +105,23 @@ def test_restore_latency( We only test a single guest kernel, as the guest kernel does not "participate" in snapshot restore. """ - vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) - - snapshot = vm.snapshot_full() - vm.kill() + vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs) - metrics.put_dimensions( - {"performance_test": "test_restore_latency", "uffd_handler": "None"} + metrics.set_dimensions( + { + "net_devices": str(test_setup.nets), + "block_devices": str(test_setup.blocks), + "vsock_devices": str(int(test_setup.all_devices)), + "balloon_devices": str(int(test_setup.all_devices)), + "huge_pages_config": str(test_setup.huge_pages), + "performance_test": "test_restore_latency", + "uffd_handler": "None", + **vm.dimensions, + } ) + snapshot = vm.snapshot_full() + vm.kill() for microvm in microvm_factory.build_n_from_snapshot(snapshot, ITERATIONS): value = 0 # Parse all metric data points in search of load_snapshot time. @@ -151,7 +149,20 @@ def test_post_restore_latency( pytest.skip("huge page snapshots can only be restored using uffd") test_setup = SnapshotRestoreTest(mem=1024, vcpus=2, huge_pages=huge_pages) - vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs, metrics) + vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs) + + metrics.set_dimensions( + { + "net_devices": str(test_setup.nets), + "block_devices": str(test_setup.blocks), + "vsock_devices": str(int(test_setup.all_devices)), + "balloon_devices": str(int(test_setup.all_devices)), + "huge_pages_config": str(test_setup.huge_pages), + "performance_test": "test_post_restore_latency", + "uffd_handler": str(uffd_handler), + **vm.dimensions, + } + ) vm.ssh.check_output( "nohup /usr/local/bin/fast_page_fault_helper >/dev/null 2>&1 Date: Fri, 28 Feb 2025 16:31:03 +0000 Subject: [PATCH 311/464] feat: Generate bindings to enable Intel AMX's TILEDATA for XSAVE Bindings for ARCH_REQ_XCOMP_GUEST_PERM and ARCH_XCOMP_TILEDATA are required to enable Intel AMX's XTILEDATA for XSAVE. Note that the required bits were added in kernel v6.4+. Signed-off-by: Takahiro Itazuri --- src/vmm/src/arch/x86_64/gen/arch_prctl.rs | 43 +++++++++++++++++++++++ src/vmm/src/arch/x86_64/gen/mod.rs | 2 +- tools/bindgen.sh | 9 +++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/vmm/src/arch/x86_64/gen/arch_prctl.rs diff --git a/src/vmm/src/arch/x86_64/gen/arch_prctl.rs b/src/vmm/src/arch/x86_64/gen/arch_prctl.rs new file mode 100644 index 00000000000..768964e494b --- /dev/null +++ b/src/vmm/src/arch/x86_64/gen/arch_prctl.rs @@ -0,0 +1,43 @@ +// 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 +)] + +pub const ARCH_SET_GS: u32 = 4097; +pub const ARCH_SET_FS: u32 = 4098; +pub const ARCH_GET_FS: u32 = 4099; +pub const ARCH_GET_GS: u32 = 4100; +pub const ARCH_GET_CPUID: u32 = 4113; +pub const ARCH_SET_CPUID: u32 = 4114; +pub const ARCH_GET_XCOMP_SUPP: u32 = 4129; +pub const ARCH_GET_XCOMP_PERM: u32 = 4130; +pub const ARCH_REQ_XCOMP_PERM: u32 = 4131; +pub const ARCH_GET_XCOMP_GUEST_PERM: u32 = 4132; +pub const ARCH_REQ_XCOMP_GUEST_PERM: u32 = 4133; +pub const ARCH_XCOMP_TILECFG: u32 = 17; +pub const ARCH_XCOMP_TILEDATA: u32 = 18; +pub const ARCH_MAP_VDSO_X32: u32 = 8193; +pub const ARCH_MAP_VDSO_32: u32 = 8194; +pub const ARCH_MAP_VDSO_64: u32 = 8195; +pub const ARCH_GET_UNTAG_MASK: u32 = 16385; +pub const ARCH_ENABLE_TAGGED_ADDR: u32 = 16386; +pub const ARCH_GET_MAX_TAG_BITS: u32 = 16387; +pub const ARCH_FORCE_TAGGED_SVA: u32 = 16388; +pub const ARCH_SHSTK_ENABLE: u32 = 20481; +pub const ARCH_SHSTK_DISABLE: u32 = 20482; +pub const ARCH_SHSTK_LOCK: u32 = 20483; +pub const ARCH_SHSTK_UNLOCK: u32 = 20484; +pub const ARCH_SHSTK_STATUS: u32 = 20485; +pub const ARCH_SHSTK_SHSTK: u32 = 1; +pub const ARCH_SHSTK_WRSS: u32 = 2; diff --git a/src/vmm/src/arch/x86_64/gen/mod.rs b/src/vmm/src/arch/x86_64/gen/mod.rs index 35c2ca225e8..bded9e51455 100644 --- a/src/vmm/src/arch/x86_64/gen/mod.rs +++ b/src/vmm/src/arch/x86_64/gen/mod.rs @@ -5,9 +5,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. +pub mod arch_prctl; pub mod hyperv; pub mod hyperv_tlfs; pub mod mpspec; - pub mod msr_index; pub mod perf_event; diff --git a/tools/bindgen.sh b/tools/bindgen.sh index e2698b81daf..6c64bc5be93 100755 --- a/tools/bindgen.sh +++ b/tools/bindgen.sh @@ -154,6 +154,15 @@ fc-bindgen \ "amazonlinux-v5.10.y/include/uapi/linux/io_uring.h" \ >src/vmm/src/io_uring/gen.rs +# Latest upstream kernel +KERNEL_SRC_DIR="linux" +[ -d ${KERNEL_SRC_DIR} ] || git clone --depth 1 https://github.com/amazonlinux/linux ${KERNEL_SRC_DIR} + +info "BINDGEN asm/prctl.h" +fc-bindgen \ + --allowlist-var "ARCH_.*" \ + "${KERNEL_SRC_DIR}/arch/x86/include/uapi/asm/prctl.h" >src/vmm/src/arch/x86_64/gen/arch_prctl.rs + # Apply any patches info "Apply patches" for PATCH in $(dirname $0)/bindgen-patches/*.patch; do From d20ab9181ede4452635c092a7022cccd1e9a10e4 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 28 Feb 2025 19:02:12 +0000 Subject: [PATCH 312/464] refactor: Remove Eq and PartialEq from KvmError Eq and PartialEq are not necessary for KvmError, rather disallows me to add error variants wrapping std::io::Error to handle syscall errors. Signed-off-by: Takahiro Itazuri --- src/vmm/src/vstate/kvm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index 20585b337fc..48587e0331b 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -13,7 +13,7 @@ use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work #[rustfmt::skip] -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +#[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum KvmError { /// The host kernel reports an invalid KVM API version: {0} ApiVersion(i32), From d44732df5cd93cad04d2e63bdd7d81b2728c7e08 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 3 Mar 2025 14:35:15 +0000 Subject: [PATCH 313/464] feat(vmm): Request permission for Intel AMX Intel AMX (Advanced Matrix Extensions) was introduced in Intel Sapphire Rapids to accelerate deep learning and AI workloads. Since it requires a larger area to save its state, the TILEDATA feature is disabled by default. We request permission for it by default because it can be disabled via CPU template. Otherwise, kernels prior to v6.4 have a bug where KVM_GET_SUPPORTED_CPUID returns an inconsistent state of TILECFG enabled but TILEDATA disabled by default, causing guest's #GP fault on xsetbv instruction. Signed-off-by: Takahiro Itazuri --- src/vmm/Cargo.toml | 2 +- src/vmm/src/arch/x86_64/mod.rs | 2 + src/vmm/src/arch/x86_64/xstate.rs | 136 ++++++++++++++++++++++++++++++ src/vmm/src/vstate/kvm.rs | 7 ++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/vmm/src/arch/x86_64/xstate.rs diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index f1464a0a585..725190eb3ce 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" bench = false [dependencies] -acpi_tables = { path = "../acpi-tables" } +acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } aws-lc-rs = { version = "1.12.4", features = ["bindgen"] } diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 80030216fdb..973e7235c98 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -19,6 +19,8 @@ mod mptable; pub mod msr; /// Logic for configuring x86_64 registers. pub mod regs; +/// Logic for configuring XSTATE features. +pub mod xstate; #[allow(missing_docs)] pub mod gen; diff --git a/src/vmm/src/arch/x86_64/xstate.rs b/src/vmm/src/arch/x86_64/xstate.rs new file mode 100644 index 00000000000..91197d076ba --- /dev/null +++ b/src/vmm/src/arch/x86_64/xstate.rs @@ -0,0 +1,136 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use vmm_sys_util::syscall::SyscallReturnCode; + +use crate::arch::x86_64::gen::arch_prctl; + +const INTEL_AMX_MASK: u64 = 1u64 << arch_prctl::ARCH_XCOMP_TILEDATA; + +/// Errors assocaited with x86_64's dynamic XSAVE state features. +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum XstateError { + /// Failed to get supported XSTATE features: {0} + GetSupportedFeatures(std::io::Error), + /// Failed to request permission for XSTATE feature ({0}): {1} + RequestFeaturePermission(u32, std::io::Error), +} + +/// Request permission for all dynamic XSTATE features. +/// +/// Some XSTATE features are not permitted by default, because they may require a larger area to +/// save their states than the tranditional 4096-byte area. Instead, the permission for them can be +/// requested via arch_prctl(). +/// https://github.com/torvalds/linux/blob/master/Documentation/arch/x86/xstate.rst +/// +/// Firecracker requests permission for them by default if available in order to retrieve the +/// full supported feature set via KVM_GET_SUPPORTED_CPUID. +/// https://docs.kernel.org/virt/kvm/api.html#kvm-get-supported-cpuid +/// +/// Note that requested features can be masked by a CPU template. +pub fn request_dynamic_xstate_features() -> Result<(), XstateError> { + let supported_xfeatures = + match get_supported_xfeatures().map_err(XstateError::GetSupportedFeatures)? { + Some(supported_xfeatures) => supported_xfeatures, + // Exit early if dynamic XSTATE feature enabling is not supported on the kernel. + None => return Ok(()), + }; + + // Intel AMX's TILEDATA + // + // Unless requested, on kernels prior to v6.4, KVM_GET_SUPPORTED_CPUID returns an + // inconsistent state where TILECFG is set but TILEDATA isn't. Such a half-enabled state + // causes guest crash during boot because a guest calls XSETBV instruction with all + // XSAVE feature bits enumerated on CPUID and XSETBV only accepts either of both Intel + // AMX bits enabled or disabled; otherwise resulting in general protection fault. + if supported_xfeatures & INTEL_AMX_MASK == INTEL_AMX_MASK { + request_xfeature_permission(arch_prctl::ARCH_XCOMP_TILEDATA).map_err(|err| { + XstateError::RequestFeaturePermission(arch_prctl::ARCH_XCOMP_TILEDATA, err) + })?; + } + + Ok(()) +} + +/// Get supported XSTATE features +/// +/// Returns Ok(None) if dynamic XSTATE feature enabling is not supported. +fn get_supported_xfeatures() -> Result, std::io::Error> { + let mut supported_xfeatures: u64 = 0; + + // SAFETY: Safe because the third input (`addr`) is a valid `c_ulong` pointer. + // https://man7.org/linux/man-pages/man2/arch_prctl.2.html + match SyscallReturnCode(unsafe { + libc::syscall( + libc::SYS_arch_prctl, + arch_prctl::ARCH_GET_XCOMP_SUPP, + &mut supported_xfeatures as *mut libc::c_ulong, + ) + }) + .into_empty_result() + { + Ok(()) => Ok(Some(supported_xfeatures)), + // EINVAL is returned if the dynamic XSTATE feature enabling is not supported (e.g. kernel + // version prior to v5.17). + // https://github.com/torvalds/linux/commit/980fe2fddcff21937c93532b4597c8ea450346c1 + Err(err) if err.raw_os_error() == Some(libc::EINVAL) => Ok(None), + Err(err) => Err(err), + } +} + +/// Request permission for a dynamic XSTATE feature. +/// +/// This should be called after `get_supported_xfeatures()` that also checks that dynamic XSTATE +/// feature enabling is supported. +fn request_xfeature_permission(xfeature: u32) -> Result<(), std::io::Error> { + // SAFETY: Safe because the third input (`addr`) is a valid `c_ulong` value. + // https://man7.org/linux/man-pages/man2/arch_prctl.2.html + SyscallReturnCode(unsafe { + libc::syscall( + libc::SYS_arch_prctl, + arch_prctl::ARCH_REQ_XCOMP_GUEST_PERM as libc::c_ulong, + xfeature as libc::c_ulong, + ) + }) + .into_empty_result() +} + +#[cfg(test)] +mod tests { + use super::*; + + // Get permitted XSTATE features. + fn get_permitted_xstate_features() -> Result { + let mut permitted_xfeatures: u64 = 0; + // SAFETY: Safe because the third input (`addr`) is a valid `c_ulong` pointer. + match SyscallReturnCode(unsafe { + libc::syscall( + libc::SYS_arch_prctl, + arch_prctl::ARCH_GET_XCOMP_GUEST_PERM, + &mut permitted_xfeatures as *mut libc::c_ulong, + ) + }) + .into_empty_result() + { + Ok(()) => Ok(permitted_xfeatures), + Err(err) => Err(err), + } + } + + #[test] + fn test_request_xstate_feature_permission() { + request_dynamic_xstate_features().unwrap(); + + let supported_xfeatures = match get_supported_xfeatures().unwrap() { + Some(supported_xfeatures) => supported_xfeatures, + // Nothing to test if dynamic XSTATE feature enabling is not supported on the kernel. + None => return, + }; + + // Check each dynamic feature is enabled. (currently only Intel AMX TILEDATA) + if supported_xfeatures & INTEL_AMX_MASK == INTEL_AMX_MASK { + let permitted_xfeatures = get_permitted_xstate_features().unwrap(); + assert_eq!(permitted_xfeatures & INTEL_AMX_MASK, INTEL_AMX_MASK); + } + } +} diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index 48587e0331b..c7d29b449c5 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -7,6 +7,8 @@ use kvm_bindings::{CpuId, MsrList, KVM_MAX_CPUID_ENTRIES}; use kvm_ioctls::Kvm as KvmFd; use serde::{Deserialize, Serialize}; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86_64::xstate::{request_dynamic_xstate_features, XstateError}; use crate::cpu_config::templates::KvmCapability; use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; @@ -27,6 +29,9 @@ pub enum KvmError { GetSupportedCpuId(kvm_ioctls::Error), /// The number of configured slots is bigger than the maximum reported by KVM NotEnoughMemorySlots, + #[cfg(target_arch = "x86_64")] + /// Failed to request permission for dynamic XSTATE features: {0} + XstateFeatures(XstateError), } /// Struct with kvm fd and kvm associated paramenters. @@ -73,6 +78,8 @@ impl Kvm { #[cfg(target_arch = "x86_64")] { + request_dynamic_xstate_features().map_err(KvmError::XstateFeatures)?; + let supported_cpuid = kvm_fd .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) .map_err(KvmError::GetSupportedCpuId)?; From 803140d8249d3c36f5319aaa215466aa2e5a7bd3 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 7 Mar 2025 10:18:23 +0000 Subject: [PATCH 314/464] feat(vmm): Use structs and methods for `KVM_CAP_XSAVE2` Intel AMX is an XSTATE feature and TILEDATA is disabled by default because it requires a larger area to save its state than the traditional 4096 bytes. Instead, Linux kernel allows VMMs to request the guest permission via `arch_prctl()`. As such, the size of the XSTATE buffer required to save XSTASTE is dynamic. To support dynamically-sized buffer, `KVM_CAP_XSAVE2` was introduced with `KVM_GET_XSAVE2`. Accordingly, kvm-bindings added `Xsave` that is an alias of `FamStructWrapper` for the `kvm_xsave` struct with FAM in the end, and kvm-ioctls added `get_xsave2()` for `KVM_GET_XSAVE2` and `set_xsave2()` to take `Xsave` to call `KVM_SET_XSAVE`. Change the type of `xsave` in `VcpuState` from `kvm_xsave` to `Xsave`. Use `get_xsave2()` and `set_xsave2()`. Signed-off-by: Takahiro Itazuri --- Cargo.lock | 8 +-- src/vmm/Cargo.toml | 4 +- src/vmm/src/vstate/vcpu/x86_64.rs | 93 ++++++++++++++++++++++++++++--- src/vmm/src/vstate/vm/x86_64.rs | 39 ++++++++++++- 4 files changed, 127 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6774369a2b2..6244987459e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -825,9 +825,9 @@ dependencies = [ [[package]] name = "kvm-bindings" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501bc0717c6a9fc409f29047ebeb6040a4d304344698abb268c4c6a440e6a09a" +checksum = "3b13baf7bdfda2e10bcb109fcb099ef40cff82374eb6b7cdcf4695bdec4e522c" dependencies = [ "serde", "vmm-sys-util", @@ -836,9 +836,9 @@ dependencies = [ [[package]] name = "kvm-ioctls" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9120f23310f01dd7b4fbb4ae1fd4eae3e09a7aa5b77038b08a6b37099d8ef4" +checksum = "083c460d5a272c2f22205973e319147b791d92a288d7d7a8d4c6194f95229440" dependencies = [ "bitflags 2.8.0", "kvm-bindings", diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 725190eb3ce..0e5c90f56e1 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -22,8 +22,8 @@ displaydoc = "0.2.5" event-manager = "0.4.0" gdbstub = { version = "0.7.3", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } -kvm-bindings = { version = "0.11.0", features = ["fam-wrappers", "serde"] } -kvm-ioctls = "0.20.0" +kvm-bindings = { version = "0.11.1", features = ["fam-wrappers", "serde"] } +kvm-ioctls = "0.21.0" libc = "0.2.170" linux-loader = "0.13.0" log = { version = "0.4.26", features = ["std", "serde"] } diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 7f223b4daa9..1cadab157a1 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -10,12 +10,12 @@ use std::fmt::Debug; use kvm_bindings::{ kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, - kvm_xsave, CpuId, Msrs, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES, + kvm_xsave, kvm_xsave2, CpuId, Msrs, Xsave, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES, }; use kvm_ioctls::{VcpuExit, VcpuFd}; use log::{error, warn}; use serde::{Deserialize, Serialize}; -use vmm_sys_util::fam; +use vmm_sys_util::fam::{self, FamStruct}; use crate::arch::x86_64::gen::msr_index::{MSR_IA32_TSC, MSR_IA32_TSC_DEADLINE}; use crate::arch::x86_64::interrupts; @@ -74,8 +74,10 @@ pub enum KvmVcpuError { VcpuGetVcpuEvents(kvm_ioctls::Error), /// Failed to get KVM vcpu xcrs: {0} VcpuGetXcrs(kvm_ioctls::Error), - /// Failed to get KVM vcpu xsave: {0} + /// Failed to get KVM vcpu xsave via KVM_GET_XSAVE: {0} VcpuGetXsave(kvm_ioctls::Error), + /// Failed to get KVM vcpu xsave via KVM_GET_XSAVE2: {0} + VcpuGetXsave2(kvm_ioctls::Error), /// Failed to get KVM vcpu cpuid: {0} VcpuGetCpuid(kvm_ioctls::Error), /// Failed to get KVM TSC frequency: {0} @@ -147,6 +149,10 @@ pub struct KvmVcpu { /// The list of MSRs to include in a VM snapshot, in the same order as KVM returned them /// from KVM_GET_MSR_INDEX_LIST msrs_to_save: Vec, + /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct. + /// + /// `None` if `KVM_CAP_XSAVE2` not supported. + xsave2_size: Option, } /// Vcpu peripherals @@ -176,6 +182,7 @@ impl KvmVcpu { fd: kvm_vcpu, peripherals: Default::default(), msrs_to_save: vm.msrs_to_save().to_vec(), + xsave2_size: vm.xsave2_size(), }) } @@ -263,6 +270,66 @@ impl KvmVcpu { self.peripherals.pio_bus = Some(pio_bus); } + /// Get the current XSAVE state for this vCPU. + /// + /// The C `kvm_xsave` struct was extended by adding a flexible array member (FAM) in the end + /// to support variable-sized XSTATE buffer. + /// + /// https://elixir.bootlin.com/linux/v6.13.6/source/arch/x86/include/uapi/asm/kvm.h#L381 + /// ```c + /// struct kvm_xsave { + /// __u32 region[1024]; + /// __u32 extra[]; + /// }; + /// ``` + /// + /// As shown above, the C `kvm_xsave` struct does not have any field for the size of itself or + /// the length of its FAM. The required size (in bytes) of `kvm_xsave` struct can be retrieved + /// via `KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2)`. + /// + /// kvm-bindings defines `kvm_xsave2` struct that wraps the `kvm_xsave` struct to have `len` + /// field that indicates the number of FAM entries (i.e. `extra`), it also defines `Xsave` as + /// a `FamStructWrapper` of `kvm_xsave2`. + /// + /// https://github.com/rust-vmm/kvm/blob/68fff5491703bf32bd35656f7ba994a4cae9ea7d/kvm-bindings/src/x86_64/fam_wrappers.rs#L106 + /// ```rs + /// pub struct kvm_xsave2 { + /// pub len: usize, + /// pub xsave: kvm_xsave, + /// } + /// ``` + fn get_xsave(&self) -> Result { + match self.xsave2_size { + // if `KVM_CAP_XSAVE2` supported + Some(xsave2_size) => { + // Convert the `kvm_xsave` size in bytes to the length of FAM (i.e. `extra`). + let fam_len = + // Calculate the size of FAM (`extra`) area in bytes. Note that the subtraction + // never underflows because `KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2)` always returns + // at least 4096 bytes that is the size of `kvm_xsave` without FAM area. + (xsave2_size - std::mem::size_of::()) + // Divide by the size of FAM (`extra`) entry (i.e. `__u32`). + .div_ceil(std::mem::size_of::<::Entry>()); + let mut xsave = Xsave::new(fam_len).map_err(KvmVcpuError::Fam)?; + // SAFETY: Safe because `xsave` is allocated with enough size to save XSTATE. + unsafe { self.fd.get_xsave2(&mut xsave) }.map_err(KvmVcpuError::VcpuGetXsave2)?; + Ok(xsave) + } + // if `KVM_CAP_XSAVE2` not supported + None => Ok( + // SAFETY: The content is correctly laid out. + unsafe { + Xsave::from_raw(vec![kvm_xsave2 { + // Note that `len` is the number of FAM (`extra`) entries that didn't exist + // on older kernels not supporting `KVM_CAP_XSAVE2`. Thus, it's always zero. + len: 0, + xsave: self.fd.get_xsave().map_err(KvmVcpuError::VcpuGetXsave)?, + }]) + }, + ), + } + } + /// Get the current TSC frequency for this vCPU. /// /// # Errors @@ -496,7 +563,7 @@ impl KvmVcpu { .map_err(KvmVcpuError::VcpuGetMpState)?; let regs = self.fd.get_regs().map_err(KvmVcpuError::VcpuGetRegs)?; let sregs = self.fd.get_sregs().map_err(KvmVcpuError::VcpuGetSregs)?; - let xsave = self.fd.get_xsave().map_err(KvmVcpuError::VcpuGetXsave)?; + let xsave = self.get_xsave()?; let xcrs = self.fd.get_xcrs().map_err(KvmVcpuError::VcpuGetXcrs)?; let debug_regs = self .fd @@ -601,9 +668,17 @@ impl KvmVcpu { self.fd .set_sregs(&state.sregs) .map_err(KvmVcpuError::VcpuSetSregs)?; - self.fd - .set_xsave(&state.xsave) - .map_err(KvmVcpuError::VcpuSetXsave)?; + // SAFETY: Safe unless the snapshot is corrupted. + unsafe { + // kvm-ioctl's `set_xsave2()` can be called even on kernel versions not supporting + // `KVM_CAP_XSAVE2`, because it internally calls `KVM_SET_XSAVE` API that was extended + // by Linux kernel. Thus, `KVM_SET_XSAVE2` API does not exist as a KVM interface. + // However, kvm-ioctl added `set_xsave2()` to allow users to pass `Xsave` instead of the + // older `kvm_xsave`. + self.fd + .set_xsave2(&state.xsave) + .map_err(KvmVcpuError::VcpuSetXsave)?; + } self.fd .set_xcrs(&state.xcrs) .map_err(KvmVcpuError::VcpuSetXcrs)?; @@ -684,7 +759,7 @@ pub struct VcpuState { /// Xcrs. pub xcrs: kvm_xcrs, /// Xsave. - pub xsave: kvm_xsave, + pub xsave: Xsave, /// Tsc khz. pub tsc_khz: Option, } @@ -744,7 +819,7 @@ mod tests { sregs: Default::default(), vcpu_events: Default::default(), xcrs: Default::default(), - xsave: Default::default(), + xsave: Xsave::new(0).unwrap(), tsc_khz: Some(0), } } diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index c68e3c3fb1c..ef190b59036 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -7,7 +7,7 @@ use kvm_bindings::{ kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, MsrList, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, }; -use kvm_ioctls::VmFd; +use kvm_ioctls::{Cap, VmFd}; use serde::{Deserialize, Serialize}; use crate::arch::x86_64::msr::MsrError; @@ -19,6 +19,8 @@ use crate::vstate::vm::VmError; #[cfg(target_arch = "x86_64")] #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] pub enum ArchVmError { + /// Failed to check KVM capability (0): {1} + CheckCapability(Cap, kvm_ioctls::Error), /// Set PIT2 error: {0} SetPit2(kvm_ioctls::Error), /// Set clock error: {0} @@ -48,6 +50,10 @@ pub enum ArchVmError { pub struct ArchVm { pub(super) fd: VmFd, msrs_to_save: MsrList, + /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct. + /// + /// `None` if `KVM_CAP_XSAVE2` not supported. + xsave2_size: Option, } impl ArchVm { @@ -57,10 +63,34 @@ impl ArchVm { let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; + // `KVM_CAP_XSAVE2` was introduced to support dynamically-sized XSTATE buffer in kernel + // v5.17. `KVM_GET_EXTENSION(KVM_CAP_XSAVE2)` returns the required size in byte if + // supported; otherwise returns 0. + // https://github.com/torvalds/linux/commit/be50b2065dfa3d88428fdfdc340d154d96bf6848 + // + // Cache the value in order not to call it at each vCPU creation. + let xsave2_size = match fd.check_extension_int(Cap::Xsave2) { + // Catch all negative values just in case although the possible negative return value + // of ioctl() is only -1. + ..=-1 => { + return Err(VmError::Arch(ArchVmError::CheckCapability( + Cap::Xsave2, + vmm_sys_util::errno::Error::last(), + ))); + } + 0 => None, + // SAFETY: Safe because negative values are handled above. + ret => Some(usize::try_from(ret).unwrap()), + }; + fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) .map_err(ArchVmError::SetTssAddress)?; - Ok(ArchVm { fd, msrs_to_save }) + Ok(ArchVm { + fd, + msrs_to_save, + xsave2_size, + }) } pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { @@ -162,6 +192,11 @@ impl ArchVm { pub fn msrs_to_save(&self) -> &[u32] { self.msrs_to_save.as_slice() } + + /// Gets the size (in bytes) of the `kvm_xsave` struct. + pub fn xsave2_size(&self) -> Option { + self.xsave2_size + } } #[derive(Default, Deserialize, Serialize)] From 60f75c2d08fee5f4fa0e5ce899fa339e882d9381 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 10 Mar 2025 08:08:28 +0000 Subject: [PATCH 315/464] feat(seccomp): Allow to call KVM_GET_XSAVE2 KVM_GET_XSAVE2 is called when taking a snapshot, so it has to be allowed by seccomp filter. Signed-off-by: Takahiro Itazuri --- resources/seccomp/x86_64-unknown-linux-musl.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/seccomp/x86_64-unknown-linux-musl.json b/resources/seccomp/x86_64-unknown-linux-musl.json index 4920b68bacc..95ceca1b7ef 100644 --- a/resources/seccomp/x86_64-unknown-linux-musl.json +++ b/resources/seccomp/x86_64-unknown-linux-musl.json @@ -1078,6 +1078,18 @@ } ] }, + { + "syscall": "ioctl", + "args": [ + { + "index": 1, + "type": "dword", + "op": "eq", + "val": 2415963855, + "comment": "KVM_GET_XSAVE2" + } + ] + }, { "syscall": "ioctl", "args": [ From cb71cd7bb97e52c0717714fa277b76c9746c003e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 5 Mar 2025 18:04:14 +0000 Subject: [PATCH 316/464] test: Detect Intel Sapphire Rapids as CPU model Intel AMX support was introduced but it is only supported on Intel Sapphire Rapids at the moment. We have to skip Intel AMX tests on older processors. Signed-off-by: Takahiro Itazuri --- tests/framework/utils_cpuid.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py index 979f4478c8b..a3988bf7f85 100644 --- a/tests/framework/utils_cpuid.py +++ b/tests/framework/utils_cpuid.py @@ -32,6 +32,7 @@ class CpuModel(str, Enum): INTEL_SKYLAKE = "INTEL_SKYLAKE" INTEL_CASCADELAKE = "INTEL_CASCADELAKE" INTEL_ICELAKE = "INTEL_ICELAKE" + INTEL_SAPPHIRE_RAPIDS = "INTEL_SAPPHIRE_RAPIDS" CPU_DICT = { @@ -40,6 +41,7 @@ class CpuModel(str, Enum): "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", }, CpuVendor.AMD: {"AMD EPYC 7R13": "AMD_MILAN", "AMD EPYC 9R14": "AMD_GENOA"}, CpuVendor.ARM: { @@ -83,6 +85,8 @@ def get_cpu_codename(default="Unknown"): result = re.match(r"^(.*) @.*$", cpu_model) if result: return CPU_DICT[CpuVendor.INTEL].get(result.group(1), default) + # Some Intel CPUs (e.g. Intel Sapphire Rapids) don't include "@ ". + return CPU_DICT[CpuVendor.INTEL].get(cpu_model, default) if vendor == CpuVendor.AMD: result = re.match(r"^(.*) [0-9]*-Core Processor$", cpu_model) if result: From a667480ffece800dc732b729c4e63e58f3aabf2d Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 10 Mar 2025 10:01:54 +0000 Subject: [PATCH 317/464] test: Verify Intel AMX is reported inside guest To check that Intel AMX is indeed supported inside guest, check related features are listed in CPUID output. Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_x86_64.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) 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 dce36254cb6..270e3fa12e2 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -979,3 +979,37 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template_any): 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), + reason="Intel AMX is only supported on Intel Sapphire Rapids and kernel v5.17+", +) +def test_intel_amx_reported_on_sapphire_rapids( + microvm_factory, guest_kernel_linux_6_1, rootfs +): + """ + Verifies that Intel AMX is reported on guest (v5.17+) + """ + uvm = microvm_factory.build(guest_kernel_linux_6_1, rootfs) + uvm.spawn() + uvm.basic_config() + uvm.add_net_iface() + uvm.start() + + expected_dict = { + "AMX-BF16: tile bfloat16 support": "true", # CPUID.(EAX=07H,ECX=0):EDX[22] + "AMX-TILE: tile architecture support": "true", # CPUID.(EAX=07H,ECX=0):EDX[24] + "AMX-INT8: tile 8-bit integer support": "true", # CPUID.(EAX=07H,ECX=0):EDX[25] + "AMX-FP16: FP16 tile operations": "false", # CPUID.(EAX=07H,ECX=1):EAX[21], not supported on host as well + "XTILECFG state": "true", # CPUID.(EAX=0DH,ECX=0):EAX[17] + "XTILEDATA state": "true", # CPUID.(EAX=0DH,ECX=0):EAX[17] + } + cpuid_utils.check_guest_cpuid_output( + uvm, + "cpuid -1", + None, + "=", + expected_dict, + ) From 1accef6661f63de77f24d132c6628d3cd7673f6e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Mon, 10 Mar 2025 10:14:05 +0000 Subject: [PATCH 318/464] chore: Declare Intel AMX support in README Now all the required changes for Intel AMX have been done :) Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96d3f2a7a81..965c763e524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to ### Added +- [#5065](https://github.com/firecracker-microvm/firecracker/pull/5065) Added + support for Intel AMX (Advanced Matrix Extensions). + ### Changed ### Deprecated From 5277cbbd25f732c78e5a415cb5ee19e2675b5fe0 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 10 Mar 2025 11:47:35 +0000 Subject: [PATCH 319/464] chore: Update fingerprint We received a backport adding KVM support for physical timers on ARM. As a result two new registers are set: - CNTHP_CTL_EL2 - CNTHPS_CVAL_EL2 Updated the fingerprint to include these new registers. Signed-off-by: Jack Thomson --- .../fingerprint_ARM_NEOVERSE_N1_5.10host.json | 12 ++++++++++-- .../fingerprint_ARM_NEOVERSE_N1_6.1host.json | 12 ++++++++++-- .../fingerprint_ARM_NEOVERSE_V1_5.10host.json | 12 ++++++++++-- .../fingerprint_ARM_NEOVERSE_V1_6.1host.json | 12 ++++++++++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_5.10host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_5.10host.json index 5bde87f4434..ddf33a21b70 100644 --- a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_5.10host.json @@ -1,6 +1,6 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.214-202.855.amzn2.aarch64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.aarch64", "microcode_version": "0x00000000000000ff", "bios_version": "1.0", "bios_revision": "1.0", @@ -836,6 +836,14 @@ "addr": "0x603000000013df02", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, { "addr": "0x603000000013df19", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_6.1host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_6.1host.json index 374fcfb2804..7c9f701d409 100644 --- a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_N1_6.1host.json @@ -1,6 +1,6 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.aarch64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.aarch64", "microcode_version": "0x00000000000000ff", "bios_version": "1.0", "bios_revision": "1.0", @@ -796,6 +796,14 @@ "addr": "0x603000000013df02", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, { "addr": "0x603000000013df19", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_5.10host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_5.10host.json index eea613e7749..ef8ca24a9e3 100644 --- a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_5.10host.json @@ -1,6 +1,6 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.214-202.855.amzn2.aarch64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.aarch64", "microcode_version": "0x0000000000000001", "bios_version": "1.0", "bios_revision": "1.0", @@ -836,6 +836,14 @@ "addr": "0x603000000013df02", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, { "addr": "0x603000000013df19", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_6.1host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_6.1host.json index 5be097ea316..b5c7d395709 100644 --- a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V1_6.1host.json @@ -1,6 +1,6 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.aarch64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.aarch64", "microcode_version": "0x0000000000000001", "bios_version": "1.0", "bios_revision": "1.0", @@ -796,6 +796,14 @@ "addr": "0x603000000013df02", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, { "addr": "0x603000000013df19", "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" From 0b32062224edda63f1daec13f317d24d909274fb Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 10 Mar 2025 15:27:41 +0000 Subject: [PATCH 320/464] test: Enable reset physical counter on AL Enable the physical counter tests to run on amazon linux 2 or 2023 as the KVM support for these has been backported from 6.4. Signed-off-by: Jack Thomson --- .../functional/test_snapshot_basic.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 09e14b92448..095bd6627ba 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -514,11 +514,13 @@ def test_vmgenid(guest_kernel_linux_6_1, rootfs, microvm_factory, snapshot_type) check_vmgenid_update_count(vm, i + 1) -# TODO add `global_props.host_os == "amzn2"` condition -# once amazon linux kernels have patches. @pytest.mark.skipif( - platform.machine() != "aarch64" or global_props.host_linux_version_tpl < (6, 4), - reason="This is aarch64 specific test and should only be run on 6.4 and later kernels", + platform.machine() != "aarch64" + or ( + global_props.host_linux_version_tpl < (6, 4) + and global_props.host_os not in ("amzn2", "amzn2023") + ), + reason="This test requires aarch64 and either kernel 6.4+ or Amazon Linux", ) def test_physical_counter_reset_aarch64(uvm_nano): """ From d2db352f5088f9d12204d7d0dfbfb631edb0b8c0 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 10 Mar 2025 17:12:47 +0000 Subject: [PATCH 321/464] test: Bump physical counter comparison Use a bigger comparison during our assertion of the physical counter reset. The previous value was a little too low and would sometimes fail. Signed-off-by: Jack Thomson --- tests/integration_tests/functional/test_snapshot_basic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 095bd6627ba..bedaae488f6 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -542,10 +542,10 @@ def test_physical_counter_reset_aarch64(uvm_nano): snap_editor = host.get_binary("snapshot-editor") cntpct_el0 = hex(0x603000000013DF01) - # If a CPU runs at 3GHz, it will have a counter value of 1_000_000_000 - # in 1/3 of a second. The host surely will run for more than 1/3 second before + # If a CPU runs at 3GHz, it will have a counter value of 8_000_000_000 + # in 2.66 seconds. The host surely will run for more than 2.66 seconds before # executing this test. - max_value = 800_000_000 + max_value = 8_000_000_000 cmd = [ str(snap_editor), From 2f9fc706fc59e0e5917a8aa016c28a7ae5600510 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 11:23:01 +0000 Subject: [PATCH 322/464] build(deps): Bump the firecracker group across 1 directory with 33 updates Bumps the firecracker group with 28 updates in the / directory: | Package | From | To | | --- | --- | --- | | [thiserror](https://github.com/dtolnay/thiserror) | `2.0.11` | `2.0.12` | | [zerocopy](https://github.com/google/zerocopy) | `0.8.20` | `0.8.23` | | [clap](https://github.com/clap-rs/clap) | `4.5.31` | `4.5.32` | | [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.93` | `1.0.94` | | [quote](https://github.com/dtolnay/quote) | `1.0.38` | `1.0.40` | | [syn](https://github.com/dtolnay/syn) | `2.0.98` | `2.0.100` | | [uuid](https://github.com/uuid-rs/uuid) | `1.14.0` | `1.15.1` | | [libc](https://github.com/rust-lang/libc) | `0.2.170` | `0.2.171` | | [serde](https://github.com/serde-rs/serde) | `1.0.218` | `1.0.219` | | [serde_json](https://github.com/serde-rs/json) | `1.0.139` | `1.0.140` | | [micro_http](https://github.com/firecracker-microvm/micro-http) | ``ef96f62`` | ``18f5b6f`` | | [cargo_toml](https://gitlab.com/lib.rs/cargo_toml) | `0.21.0` | `0.22.1` | | [env_logger](https://github.com/rust-cli/env_logger) | `0.11.6` | `0.11.7` | | [semver](https://github.com/dtolnay/semver) | `1.0.25` | `1.0.26` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.12.4` | `1.12.6` | | [bitflags](https://github.com/bitflags/bitflags) | `2.8.0` | `2.9.0` | | [gdbstub](https://github.com/daniel5151/gdbstub) | `0.7.3` | `0.7.5` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.15` | `1.2.16` | | [either](https://github.com/rayon-rs/either) | `1.14.0` | `1.15.0` | | [indexmap](https://github.com/indexmap-rs/indexmap) | `2.7.1` | `2.8.0` | | [is-terminal](https://github.com/sunfishcode/is-terminal) | `0.4.15` | `0.4.16` | | [itoa](https://github.com/dtolnay/itoa) | `1.0.14` | `1.0.15` | | [once_cell](https://github.com/matklad/once_cell) | `1.20.3` | `1.21.0` | | oorandom | `11.1.4` | `11.1.5` | | [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) | `0.2.20` | `0.2.21` | | [prettyplease](https://github.com/dtolnay/prettyplease) | `0.2.29` | `0.2.30` | | [ryu](https://github.com/dtolnay/ryu) | `1.0.19` | `1.0.20` | | [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.17` | `1.0.18` | Updates `thiserror` from 2.0.11 to 2.0.12 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/2.0.11...2.0.12) Updates `zerocopy` from 0.8.20 to 0.8.23 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.20...v0.8.23) Updates `clap` from 4.5.31 to 4.5.32 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.31...clap_complete-v4.5.32) Updates `proc-macro2` from 1.0.93 to 1.0.94 - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.94) Updates `quote` from 1.0.38 to 1.0.40 - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.38...1.0.40) Updates `syn` from 2.0.98 to 2.0.100 - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/2.0.98...2.0.100) Updates `uuid` from 1.14.0 to 1.15.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/v1.14.0...v1.15.1) Updates `libc` from 0.2.170 to 0.2.171 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.171/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171) Updates `serde` from 1.0.218 to 1.0.219 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219) Updates `serde_json` from 1.0.139 to 1.0.140 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.139...v1.0.140) Updates `micro_http` from `ef96f62` to `18f5b6f` - [Commits](https://github.com/firecracker-microvm/micro-http/compare/ef96f623c46e221ebf9b6037567f97ec57683afd...18f5b6f5f5adbc553cb85f6a9c6c319ae9b0ec69) Updates `serde_derive` from 1.0.218 to 1.0.219 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219) Updates `cargo_toml` from 0.21.0 to 0.22.1 - [Commits](https://gitlab.com/lib.rs/cargo_toml/commits/v0.22.1) Updates `env_logger` from 0.11.6 to 0.11.7 - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.6...v0.11.7) Updates `semver` from 1.0.25 to 1.0.26 - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.25...1.0.26) Updates `aws-lc-rs` from 1.12.4 to 1.12.6 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.12.4...v1.12.6) Updates `bitflags` from 2.8.0 to 2.9.0 - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](https://github.com/bitflags/bitflags/compare/2.8.0...2.9.0) Updates `gdbstub` from 0.7.3 to 0.7.5 - [Release notes](https://github.com/daniel5151/gdbstub/releases) - [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md) - [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.3...0.7.5) Updates `aws-lc-sys` from 0.26.0 to 0.27.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.26.0...aws-lc-sys/v0.27.0) Updates `cc` from 1.2.15 to 1.2.16 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.16) Updates `clap_builder` from 4.5.31 to 4.5.32 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.31...v4.5.32) Updates `clap_derive` from 4.5.28 to 4.5.32 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.28...v4.5.32) Updates `either` from 1.14.0 to 1.15.0 - [Commits](https://github.com/rayon-rs/either/compare/1.14.0...1.15.0) Updates `indexmap` from 2.7.1 to 2.8.0 - [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md) - [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0) Updates `is-terminal` from 0.4.15 to 0.4.16 - [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.15...v0.4.16) Updates `itoa` from 1.0.14 to 1.0.15 - [Release notes](https://github.com/dtolnay/itoa/releases) - [Commits](https://github.com/dtolnay/itoa/compare/1.0.14...1.0.15) Updates `once_cell` from 1.20.3 to 1.21.0 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.20.3...v1.21.0) Updates `oorandom` from 11.1.4 to 11.1.5 Updates `ppv-lite86` from 0.2.20 to 0.2.21 - [Commits](https://github.com/cryptocorrosion/cryptocorrosion/commits/ppv-lite86-0.2.21) Updates `prettyplease` from 0.2.29 to 0.2.30 - [Release notes](https://github.com/dtolnay/prettyplease/releases) - [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.29...0.2.30) Updates `ryu` from 1.0.19 to 1.0.20 - [Release notes](https://github.com/dtolnay/ryu/releases) - [Commits](https://github.com/dtolnay/ryu/compare/1.0.19...1.0.20) Updates `unicode-ident` from 1.0.17 to 1.0.18 - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.17...1.0.18) Updates `uuid-macro-internal` from 1.14.0 to 1.15.1 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/v1.14.0...v1.15.1) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: quote dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: micro_http dependency-type: direct:production dependency-group: firecracker - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cargo_toml dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: bitflags dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: gdbstub dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: clap_derive dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: either dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: indexmap dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: is-terminal dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: itoa dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: once_cell dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: oorandom dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: ppv-lite86 dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: prettyplease dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: ryu dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 247 +++++++++++++++------------ src/acpi-tables/Cargo.toml | 4 +- src/clippy-tracing/Cargo.toml | 10 +- src/cpu-template-helper/Cargo.toml | 10 +- src/firecracker/Cargo.toml | 18 +- src/jailer/Cargo.toml | 4 +- src/log-instrument-macros/Cargo.toml | 6 +- src/log-instrument/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 4 +- src/seccompiler/Cargo.toml | 12 +- src/snapshot-editor/Cargo.toml | 8 +- src/utils/Cargo.toml | 4 +- src/vmm/Cargo.toml | 18 +- 13 files changed, 189 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6244987459e..54753c8a76d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,9 @@ name = "acpi_tables" version = "0.1.0" dependencies = [ "displaydoc", - "thiserror 2.0.11", + "thiserror 2.0.12", "vm-memory", - "zerocopy 0.8.20", + "zerocopy 0.8.23", ] [[package]] @@ -141,29 +141,27 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.4" +version = "1.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd755adf9707cf671e31d944a189be3deaaeee11c8bc1d669bb8022ac90fbd0" +checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", - "paste", "untrusted", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" +checksum = "6bbe221bbf523b625a4dd8585c7f38166e31167ec2ca98051dbcb4c3b6e825d2" dependencies = [ "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", - "paste", ] [[package]] @@ -187,7 +185,7 @@ version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "lazy_static", @@ -207,7 +205,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "itertools 0.10.5", @@ -232,9 +230,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "byteorder" @@ -244,9 +242,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cargo_toml" -version = "0.21.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" +checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257" dependencies = [ "serde", "toml", @@ -260,9 +258,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.15" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -334,9 +332,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +351,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" dependencies = [ "anstream", "anstyle", @@ -365,9 +363,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", @@ -419,7 +417,7 @@ dependencies = [ "log-instrument", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "vmm", "vmm-sys-util", ] @@ -544,9 +542,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "env_filter" @@ -560,14 +558,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -612,7 +610,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "timerfd", "userfaultfd", "utils", @@ -628,11 +626,11 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "gdbstub" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c683a9f13de31432e6097131d5f385898c7f0635c0f392b9d0fa165063c8ac" +checksum = "8062b93565ea9fe2e60a0dd3c252f0d48c27cf223dad7ead028e361181a2c1a5" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "log", "managed", @@ -723,9 +721,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] name = "home" @@ -736,17 +734,11 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "indexmap" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", "hashbrown", @@ -763,9 +755,9 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", @@ -798,9 +790,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jailer" @@ -809,11 +801,35 @@ dependencies = [ "libc", "log-instrument", "regex", - "thiserror 2.0.11", + "thiserror 2.0.12", "utils", "vmm-sys-util", ] +[[package]] +name = "jiff" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "jobserver" version = "0.1.32" @@ -840,7 +856,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "083c460d5a272c2f22205973e319147b791d92a288d7d7a8d4c6194f95229440" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "kvm-bindings", "libc", "vmm-sys-util", @@ -860,9 +876,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libloading" @@ -940,7 +956,7 @@ dependencies = [ [[package]] name = "micro_http" version = "0.1.0" -source = "git+https://github.com/firecracker-microvm/micro-http#ef96f623c46e221ebf9b6037567f97ec57683afd" +source = "git+https://github.com/firecracker-microvm/micro-http#18f5b6f5f5adbc553cb85f6a9c6c319ae9b0ec69" dependencies = [ "libc", "vmm-sys-util", @@ -958,7 +974,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "libc", ] @@ -984,15 +1000,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "opaque-debug" @@ -1024,20 +1040,35 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy 0.8.23", ] [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" dependencies = [ "proc-macro2", "syn", @@ -1045,9 +1076,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -1058,7 +1089,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "lazy_static", "num-traits", "rand 0.8.5", @@ -1070,9 +1101,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1096,7 +1127,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.0", - "zerocopy 0.8.20", + "zerocopy 0.8.23", ] [[package]] @@ -1135,7 +1166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.20", + "zerocopy 0.8.23", ] [[package]] @@ -1154,7 +1185,7 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.11", + "thiserror 2.0.12", "utils", "vmm-sys-util", ] @@ -1200,7 +1231,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -1209,9 +1240,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -1232,33 +1263,33 @@ dependencies = [ "libc", "serde", "serde_json", - "thiserror 2.0.11", - "zerocopy 0.8.20", + "thiserror 2.0.12", + "zerocopy 0.8.23", ] [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -1267,9 +1298,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -1311,7 +1342,7 @@ dependencies = [ "libc", "log-instrument", "semver", - "thiserror 2.0.11", + "thiserror 2.0.12", "utils", "vmm", "vmm-sys-util", @@ -1331,9 +1362,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.98" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1351,11 +1382,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -1371,9 +1402,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", @@ -1447,9 +1478,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-xid" @@ -1479,7 +1510,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d8b176d4d3e420685e964f87c25df5fdd5b26d7eb0d0e7c892d771f5b81035" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "libc", "nix", @@ -1511,14 +1542,14 @@ dependencies = [ "displaydoc", "libc", "log-instrument", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] name = "uuid" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" +checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" dependencies = [ "getrandom 0.3.1", "rand 0.9.0", @@ -1527,9 +1558,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be57878a5f7e409a1a82be6691922b11e59687a168205b1f21b087c4acdd194" +checksum = "9521621447c21497fac206ffe6e9f642f977c4f82eeba9201055f64884d9cb01" dependencies = [ "proc-macro2", "quote", @@ -1548,7 +1579,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bce0aad4d8776cb64f1ac591e908a561c50ba6adac4416296efee590b155623f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", "uuid", "vm-memory", @@ -1598,7 +1629,7 @@ dependencies = [ "aws-lc-rs", "base64", "bincode", - "bitflags 2.8.0", + "bitflags 2.9.0", "crc64", "criterion", "derive_more", @@ -1621,7 +1652,7 @@ dependencies = [ "serde", "serde_json", "slab", - "thiserror 2.0.11", + "thiserror 2.0.12", "timerfd", "userfaultfd", "utils", @@ -1631,7 +1662,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.20", + "zerocopy 0.8.23", ] [[package]] @@ -1802,7 +1833,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -1817,11 +1848,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" dependencies = [ - "zerocopy-derive 0.8.20", + "zerocopy-derive 0.8.23", ] [[package]] @@ -1837,9 +1868,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index a854fa2a09e..717ec5d44c5 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -8,9 +8,9 @@ license = "Apache-2.0" [dependencies] displaydoc = "0.2.5" -thiserror = "2.0.11" +thiserror = "2.0.12" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.20", features = ["derive"] } +zerocopy = { version = "0.8.23", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 206d3884bfa..439f5730ee5 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -10,15 +10,15 @@ name = "clippy-tracing" bench = false [dependencies] -clap = { version = "4.5.31", features = ["derive"] } +clap = { version = "4.5.32", features = ["derive"] } itertools = "0.14.0" -proc-macro2 = { version = "1.0.93", features = ["span-locations"] } -quote = "1.0.38" -syn = { version = "2.0.98", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } +proc-macro2 = { version = "1.0.94", features = ["span-locations"] } +quote = "1.0.40" +syn = { version = "2.0.100", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.14.0", features = ["v4"] } +uuid = { version = "1.15.1", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 2a9e7f61efd..5bc7358d8e1 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,13 +10,13 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.31", features = ["derive", "string"] } +clap = { version = "4.5.32", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } -serde = { version = "1.0.218", features = ["derive"] } -serde_json = "1.0.139" -thiserror = "2.0.11" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +thiserror = "2.0.12" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index 40b2795050d..ca0c6269252 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -18,32 +18,32 @@ bench = false [dependencies] displaydoc = "0.2.5" event-manager = "0.4.0" -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -serde = { version = "1.0.218", features = ["derive"] } +serde = { version = "1.0.219", features = ["derive"] } serde_derive = "1.0.136" -serde_json = "1.0.139" -thiserror = "2.0.11" +serde_json = "1.0.140" +thiserror = "2.0.12" timerfd = "1.6.0" utils = { path = "../utils" } vmm = { path = "../vmm" } vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } [dev-dependencies] -cargo_toml = "0.21.0" -libc = "0.2.170" +cargo_toml = "0.22.1" +libc = "0.2.171" regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] } # Dev-Dependencies for uffd examples -serde = { version = "1.0.218", features = ["derive"] } +serde = { version = "1.0.219", features = ["derive"] } userfaultfd = "0.8.1" [build-dependencies] seccompiler = { path = "../seccompiler" } -serde = { version = "1.0.218" } -serde_json = "1.0.139" +serde = { version = "1.0.219" } +serde_json = "1.0.140" [features] tracing = ["log-instrument", "utils/tracing", "vmm/tracing"] diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index d3965c5070f..935971c6d1a 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -12,10 +12,10 @@ name = "jailer" bench = false [dependencies] -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } regex = { version = "1.11.1", default-features = false, features = ["std"] } -thiserror = "2.0.11" +thiserror = "2.0.12" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index 3126679cfba..b8f6cac4ad1 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -11,9 +11,9 @@ proc-macro = true bench = false [dependencies] -proc-macro2 = "1.0.93" -quote = "1.0.38" -syn = { version = "2.0.98", features = ["full", "extra-traits"] } +proc-macro2 = "1.0.94" +quote = "1.0.40" +syn = { version = "2.0.100", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index 1e7941b1b04..f1b71fd1a60 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -32,7 +32,7 @@ log = "0.4.26" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] -env_logger = "0.11.6" +env_logger = "0.11.7" [lints] workspace = true diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index b2d1dc4a90c..f121c6e2cd0 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -11,9 +11,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.11" +thiserror = "2.0.12" vmm-sys-util = "0.12.1" utils = { path = "../utils" } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index d88d2722d51..5e50a3b2615 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,13 +17,13 @@ bench = false [dependencies] bincode = "1.2.1" -clap = { version = "4.5.31", features = ["derive", "string"] } +clap = { version = "4.5.32", features = ["derive", "string"] } displaydoc = "0.2.5" -libc = "0.2.170" -serde = { version = "1.0.218", features = ["derive"] } -serde_json = "1.0.139" -thiserror = "2.0.11" -zerocopy = { version = "0.8.20" } +libc = "0.2.171" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +thiserror = "2.0.12" +zerocopy = { version = "0.8.23" } [lints] workspace = true diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 9d95dd721db..372ea2d72bb 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,14 +10,14 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.31", features = ["derive", "string"] } +clap = { version = "4.5.32", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } -semver = "1.0.25" -thiserror = "2.0.11" +semver = "1.0.26" +thiserror = "2.0.12" vmm = { path = "../vmm" } vmm-sys-util = "0.12.1" diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 0648cedb8fc..6d71fe47bf8 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -10,9 +10,9 @@ bench = false [dependencies] displaydoc = "0.2.5" -libc = "0.2.170" +libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } -thiserror = "2.0.11" +thiserror = "2.0.12" [features] tracing = ["log-instrument"] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 0e5c90f56e1..1224a00318a 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,30 +12,30 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.12.4", features = ["bindgen"] } +aws-lc-rs = { version = "1.12.6", features = ["bindgen"] } base64 = "0.22.1" bincode = "1.2.1" -bitflags = "2.8.0" +bitflags = "2.9.0" crc64 = "2.0.0" derive_more = { version = "2.0.1", default-features = false, features = ["from", "display"] } displaydoc = "0.2.5" event-manager = "0.4.0" -gdbstub = { version = "0.7.3", optional = true } +gdbstub = { version = "0.7.5", optional = true } gdbstub_arch = { version = "0.3.1", optional = true } kvm-bindings = { version = "0.11.1", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.21.0" -libc = "0.2.170" +libc = "0.2.171" linux-loader = "0.13.0" log = { version = "0.4.26", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } -semver = { version = "1.0.25", features = ["serde"] } -serde = { version = "1.0.218", features = ["derive", "rc"] } -serde_json = "1.0.139" +semver = { version = "1.0.26", features = ["serde"] } +serde = { version = "1.0.219", features = ["derive", "rc"] } +serde_json = "1.0.140" slab = "0.4.7" -thiserror = "2.0.11" +thiserror = "2.0.12" timerfd = "1.5.0" userfaultfd = "0.8.1" utils = { path = "../utils" } @@ -44,7 +44,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.20" } +zerocopy = { version = "0.8.23" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 4b7abf64d79d8adab75bf8aa9f3d7ab729d2911d Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 12 Mar 2025 15:14:04 +0000 Subject: [PATCH 323/464] fix: Clippy warnings With the update to libc these functions are no longer marked as unsafe. Updated to remove the unsafe and the wrapper function which is no longer required. Signed-off-by: Jack Thomson --- src/jailer/src/env.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index 45ede2f3434..83421b6d5d4 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -854,14 +854,6 @@ mod tests { arg_vec } - fn get_major(dev: u64) -> u32 { - unsafe { libc::major(dev) } - } - - fn get_minor(dev: u64) -> u32 { - unsafe { libc::minor(dev) } - } - fn create_env(mock_proc_mounts: &str) -> Env { // Create a standard environment. let arg_parser = build_arg_parser(); @@ -1120,8 +1112,8 @@ mod tests { // Ensure device's properties. let metadata = fs::metadata(dev_path.to_str().unwrap()).unwrap(); assert!(metadata.file_type().is_char_device()); - assert_eq!(get_major(metadata.st_rdev()), major); - assert_eq!(get_minor(metadata.st_rdev()), minor); + assert_eq!(libc::major(metadata.st_rdev()), major); + assert_eq!(libc::minor(metadata.st_rdev()), minor); assert_eq!( metadata.permissions().mode(), libc::S_IFCHR | libc::S_IRUSR | libc::S_IWUSR From cce210aad60881a7105562171913d44d03ed57cb Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Wed, 12 Mar 2025 16:03:06 +0000 Subject: [PATCH 324/464] fix: Remove redundant seccomp rule With the update to aws-lc-rs faccessat is now marked as redundant so removing it from our rules. Signed-off-by: Jack Thomson --- resources/seccomp/aarch64-unknown-linux-musl.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/resources/seccomp/aarch64-unknown-linux-musl.json b/resources/seccomp/aarch64-unknown-linux-musl.json index e618536c950..db3abe1eced 100644 --- a/resources/seccomp/aarch64-unknown-linux-musl.json +++ b/resources/seccomp/aarch64-unknown-linux-musl.json @@ -74,10 +74,6 @@ "syscall": "fstat", "comment": "Used for drive patching & rescanning, for reading the local timezone from /etc/localtime" }, - { - "syscall": "faccessat", - "comment": "Used by aws-lc-sys" - }, { "syscall": "ftruncate", "comment": "Used for snapshotting" From 1d98a21e087aa4f188f2d6e665b54c6962569199 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 12 Mar 2025 11:25:33 +0000 Subject: [PATCH 325/464] Revert "fix: test_sec_audit: ignore cargo audit output" This reverts commit d761b013db1caeec046b187927133b7fdac1375d. The output to stdout was fixed in cargo audit 0.21.2, so if we rebuild the docker container the grep is no longer necessary. In fact, the grep has broken this test in our nightly pipeline because it overwrites the return code of cargo audit itself, meaning the non-PR version of this test (which is supposed to fail if there exist any cargo audit warnings) was never failing. Signed-off-by: Patrick Roy --- tests/integration_tests/security/test_sec_audit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_tests/security/test_sec_audit.py b/tests/integration_tests/security/test_sec_audit.py index 1ad625cc7c9..e8265c3ae2a 100644 --- a/tests/integration_tests/security/test_sec_audit.py +++ b/tests/integration_tests/security/test_sec_audit.py @@ -35,6 +35,6 @@ def set_of_vulnerabilities(output: CommandReturn): ) git_ab_test_host_command_if_pr( - "cargo audit --deny warnings -q --json |grep -Po '{.*}'", + "cargo audit --deny warnings -q --json", comparator=set_did_not_grow_comparator(set_of_vulnerabilities), ) From 0debda86dea573106be973827dea51b7e6d46c37 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 12 Mar 2025 12:03:19 +0000 Subject: [PATCH 326/464] devctr: pin cargo-deny to 0.17.0 The newest 0.18.0 release requires at least rust 1.85.0 to compile. Needs to be unpinned later after toolchain upgrade. Signed-off-by: Patrick Roy --- tools/devctr/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index a9f6710a8a7..f855033fc4d 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -113,7 +113,8 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && rustup target add x86_64-unknown-linux-musl \ && rustup target add aarch64-unknown-linux-musl \ && rustup component add llvm-tools-preview clippy rustfmt \ - && cargo install --locked cargo-audit cargo-deny grcov cargo-sort cargo-afl \ + && 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 \ \ && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ From f43f4dcf6ba89023a286dc3cd349dbabb0a0e9be Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 12 Mar 2025 13:38:01 +0000 Subject: [PATCH 327/464] chore: bump devctr version v78 contains updated cargo-audit Signed-off-by: Patrick Roy --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 35794256138..9011510d7e6 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:-v77} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v78} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. From ba1e839bb4801a0642766a60b49af9a747992394 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 12 Mar 2025 18:26:25 +0000 Subject: [PATCH 328/464] fix(doc): Avoid confusion of CPUID.(EAX=0xB,ECX=1) normalization Admittedly CPUID.(EAX=0xB,ECX=1) is inserted if not present and is initialized with 0, but then similar normalization is applied as CPUID.(EAX=0xB,ECX=0). "filled with `0` is misleading. Fixes: 0aec0e4b6a73 ("doc: add doc page for cpuid normalization") Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpuid-normalization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index 3e6e54bd515..ba07b6eeae8 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -21,7 +21,7 @@ See also: [boot protocol settings](boot-protocol.md) | Enable TSC_DEADLINE | 0x1 | - | ECX | 24 | | Enable HYPERVISOR | 0x1 | - | ECX | 31 | | Set HTT value if the microVM's CPU count is greater than 1 | 0x1 | - | EDX | 28 | -| Insert leaf 0xb, subleaf 0x1 filled with `0` if it is not already present | 0xb | 0x1 | all | all | +| Insert leaf 0xb, subleaf 0x1 if not present | 0xb | 0x1 | all | all | | Update extended topology enumeration | 0xb | all | EAX | 4:0 | | Update extended topology enumeration | 0xb | all | EBX | 15:0 | | Update extended topology enumeration | 0xb | all | ECX | 15:8 | From 7c0dc1e1d5b86c496e1c4b69ebfab156c9736a13 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 12 Mar 2025 18:31:08 +0000 Subject: [PATCH 329/464] fix(doc): Simplify explanation of extended topology leaf The original doc lacks some normalization. For example, CPUID.(EAX=0xB,ECX=N):ECX[7:0] and CPUID.(EAX=0xB,ECX=N).EDX[31:00]. Honestly, there is not much value describing the details of the extended topology leaf, because no CPU features are enumerated in it and no reason to modify it using CPU template from users' perspective. Let's simply the description. Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpuid-normalization.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index ba07b6eeae8..2eb743add22 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -22,9 +22,7 @@ See also: [boot protocol settings](boot-protocol.md) | Enable HYPERVISOR | 0x1 | - | ECX | 31 | | Set HTT value if the microVM's CPU count is greater than 1 | 0x1 | - | EDX | 28 | | Insert leaf 0xb, subleaf 0x1 if not present | 0xb | 0x1 | all | all | -| Update extended topology enumeration | 0xb | all | EAX | 4:0 | -| Update extended topology enumeration | 0xb | all | EBX | 15:0 | -| Update extended topology enumeration | 0xb | all | ECX | 15:8 | +| Fill extended topology enumeration leaf | 0xb | all | all | all | | Pass through L1 cache and TLB information from host | 0x80000005 | - | all | all | | Pass through L2 cache and TLB and L3 cache information from host | 0x80000006 | - | all | all | From 8495af962404da2fbea7621cd8d44dfd7be21f1b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Mar 2025 12:07:50 +0000 Subject: [PATCH 330/464] kani: stop using deprecated cli args --enable-unstable and --restrict-vtable got deprecated in kani 0.59.0 in favor of variants based on -Z flags. So use the -Z flags instead Signed-off-by: Patrick Roy --- tests/integration_tests/test_kani.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/test_kani.py b/tests/integration_tests/test_kani.py index 0583fa4837b..9b087a5375f 100644 --- a/tests/integration_tests/test_kani.py +++ b/tests/integration_tests/test_kani.py @@ -29,12 +29,12 @@ def test_kani(results_dir): """ # -Z stubbing is required to enable the stubbing feature # -Z function-contracts is required to enable the function contracts feature - # --restrict-vtable is required for some virtio queue proofs, which go out of memory otherwise + # -Z restrict-vtable is required for some virtio queue proofs, which go out of memory otherwise # -j enables kani harnesses to be verified in parallel (required to keep CI time low) # --output-format terse is required by -j - # --enable-unstable is needed to enable `-Z` flags + # -Z unstable-options is needed to enable the other `-Z` flags _, stdout, _ = utils.check_output( - "cargo kani --enable-unstable -Z stubbing -Z function-contracts --restrict-vtable -j --output-format terse", + "cargo kani -Z unstable-options -Z stubbing -Z function-contracts -Z restrict-vtable -j --output-format terse", timeout=TIMEOUT, ) From 0fff2c8884a6f0839170c01c192574df2418ba95 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Mar 2025 13:43:43 +0000 Subject: [PATCH 331/464] buildkite: run kani if devctr is modified rebuilding the docker container can upgrade kani, and we'd like to know at the PR stage if that causes issues (such as timeouts). Signed-off-by: Patrick Roy --- .buildkite/pipeline_pr.py | 1 + 1 file changed, 1 insertion(+) diff --git a/.buildkite/pipeline_pr.py b/.buildkite/pipeline_pr.py index 46a8f6880be..5943b92e327 100755 --- a/.buildkite/pipeline_pr.py +++ b/.buildkite/pipeline_pr.py @@ -51,6 +51,7 @@ if not pipeline.args.no_kani and ( not changed_files or any(x.suffix in [".rs", ".toml", ".lock"] for x in changed_files) + or any(x.parent.name == "devctr" for x in changed_files) ): kani_grp = pipeline.build_group( "🔍 Kani", From 35d6afd2f6ac11c932e5081b810db82576abe664 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Mar 2025 14:22:01 +0000 Subject: [PATCH 332/464] refactor: stop using loops in byte_order.rs Instead of copying the buffers byte-by-byte in a loop, just use copy_from_slice, which compiles to a memcpy. While we're at it, drop some unused function definitions. Also remove the special snowflake functions for dealing with i8 slices, and instead just use zerocopy to safely transmute these into u8 slices, on which the normal functions work. Signed-off-by: Patrick Roy --- src/vmm/src/arch/x86_64/interrupts.rs | 5 +++-- src/vmm/src/utils/byte_order.rs | 29 ++++++--------------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/vmm/src/arch/x86_64/interrupts.rs b/src/vmm/src/arch/x86_64/interrupts.rs index 8b7bf8bc793..8deb5a9d44e 100644 --- a/src/vmm/src/arch/x86_64/interrupts.rs +++ b/src/vmm/src/arch/x86_64/interrupts.rs @@ -7,6 +7,7 @@ use kvm_bindings::kvm_lapic_state; use kvm_ioctls::VcpuFd; +use zerocopy::IntoBytes; use crate::utils::byte_order; @@ -28,13 +29,13 @@ const APIC_MODE_EXTINT: u32 = 0x7; fn get_klapic_reg(klapic: &kvm_lapic_state, reg_offset: usize) -> u32 { let range = reg_offset..reg_offset + 4; let reg = klapic.regs.get(range).expect("get_klapic_reg range"); - byte_order::read_le_u32_from_i8(reg) + byte_order::read_le_u32(reg.as_bytes()) } fn set_klapic_reg(klapic: &mut kvm_lapic_state, reg_offset: usize, value: u32) { let range = reg_offset..reg_offset + 4; let reg = klapic.regs.get_mut(range).expect("set_klapic_reg range"); - byte_order::write_le_u32_to_i8(reg, value) + byte_order::write_le_u32(reg.as_mut_bytes(), value); } fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 { diff --git a/src/vmm/src/utils/byte_order.rs b/src/vmm/src/utils/byte_order.rs index 32aa9daee18..c0682c494df 100644 --- a/src/vmm/src/utils/byte_order.rs +++ b/src/vmm/src/utils/byte_order.rs @@ -5,13 +5,9 @@ macro_rules! generate_read_fn { ($fn_name: ident, $data_type: ty, $byte_type: ty, $type_size: expr, $endian_type: ident) => { /// Read bytes from the slice pub fn $fn_name(input: &[$byte_type]) -> $data_type { - assert!($type_size == std::mem::size_of::<$data_type>()); - let mut array = [0u8; $type_size]; - #[allow(clippy::cast_sign_loss)] - #[allow(clippy::cast_possible_wrap)] - for (byte, read) in array.iter_mut().zip(input.iter().cloned()) { - *byte = read as u8; - } + let mut array = [0u8; std::mem::size_of::<$data_type>()]; + let how_many = input.len().min(std::mem::size_of::<$data_type>()); + array[..how_many].copy_from_slice(&input[..how_many]); <$data_type>::$endian_type(array) } }; @@ -21,32 +17,21 @@ macro_rules! generate_write_fn { ($fn_name: ident, $data_type: ty, $byte_type: ty, $endian_type: ident) => { /// Write bytes to the slice pub fn $fn_name(buf: &mut [$byte_type], n: $data_type) { - #[allow(clippy::cast_sign_loss)] - #[allow(clippy::cast_possible_wrap)] - for (byte, read) in buf - .iter_mut() - .zip(<$data_type>::$endian_type(n).iter().cloned()) - { - *byte = read as $byte_type; - } + let bytes = n.$endian_type(); + let how_much = buf.len().min(bytes.len()); + buf[..how_much].copy_from_slice(&bytes[..how_much]); } }; } -generate_read_fn!(read_le_u16, u16, u8, 2, from_le_bytes); generate_read_fn!(read_le_u32, u32, u8, 4, from_le_bytes); -generate_read_fn!(read_le_u32_from_i8, u32, i8, 4, from_le_bytes); generate_read_fn!(read_le_u64, u64, u8, 8, from_le_bytes); -generate_read_fn!(read_le_i32, i32, i8, 4, from_le_bytes); generate_read_fn!(read_be_u16, u16, u8, 2, from_be_bytes); generate_read_fn!(read_be_u32, u32, u8, 4, from_be_bytes); -generate_write_fn!(write_le_u16, u16, u8, to_le_bytes); generate_write_fn!(write_le_u32, u32, u8, to_le_bytes); -generate_write_fn!(write_le_u32_to_i8, u32, i8, to_le_bytes); generate_write_fn!(write_le_u64, u64, u8, to_le_bytes); -generate_write_fn!(write_le_i32, i32, i8, to_le_bytes); generate_write_fn!(write_be_u16, u16, u8, to_be_bytes); generate_write_fn!(write_be_u32, u32, u8, to_be_bytes); @@ -110,10 +95,8 @@ mod tests { }; } - byte_order_test_read_write!(test_le_u16, write_le_u16, read_le_u16, false, u16); byte_order_test_read_write!(test_le_u32, write_le_u32, read_le_u32, false, u32); byte_order_test_read_write!(test_le_u64, write_le_u64, read_le_u64, false, u64); - byte_order_test_read_write!(test_le_i32, write_le_i32, read_le_i32, false, i32); byte_order_test_read_write!(test_be_u16, write_be_u16, read_be_u16, true, u16); byte_order_test_read_write!(test_be_u32, write_be_u32, read_be_u32, true, u32); } From dd0d9328341b636c634da5fb028c7f46bdd424cd Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Mar 2025 14:26:29 +0000 Subject: [PATCH 333/464] kani: remove stubbing from dumbo harnesses with the byte_order modules no longer using loops, this is no longer needed. Signed-off-by: Patrick Roy --- src/vmm/src/dumbo/pdu/ethernet.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/vmm/src/dumbo/pdu/ethernet.rs b/src/vmm/src/dumbo/pdu/ethernet.rs index f93a0c5d007..bec283bbd56 100644 --- a/src/vmm/src/dumbo/pdu/ethernet.rs +++ b/src/vmm/src/dumbo/pdu/ethernet.rs @@ -255,16 +255,6 @@ mod kani_proofs { } } - mod stubs { - // The current implementation of read_be_u16 function leads to a significant - // performance degradation given a necessary loop unrolling. Using this stub, - // we read the same information from the buffer while avoiding the loop, thus, - // notably improving performance. - pub fn read_be_u16(input: &[u8]) -> u16 { - u16::from_be_bytes([input[0], input[1]]) - } - } - // We consider the MMDS Network Stack spec for all postconditions in the harnesses. // See https://github.com/firecracker-microvm/firecracker/blob/main/docs/mmds/mmds-design.md#mmds-network-stack @@ -519,7 +509,6 @@ mod kani_proofs { #[kani::proof] #[kani::solver(cadical)] - #[kani::stub(crate::utils::byte_order::read_be_u16, stubs::read_be_u16)] fn verify_with_payload_len_unchecked() { // Create non-deterministic stream of bytes up to MAX_FRAME_SIZE let mut bytes: [u8; MAX_FRAME_SIZE] = kani::Arbitrary::any_array::(); From 1b9ba6f98a1b2360a437b69cefd03f3a5a957960 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Feb 2025 12:59:39 +0000 Subject: [PATCH 334/464] test: Modernize test_send_ctrl_alt_del Instead of sleeping for 2 seconds to wait for booting, add a network device and wait for ssh availability (happens automatically in .start()). Use mark_killed() to assert that Firecracker exited instead of "waitpid". Using `waitpid(2)` here is wrong, because it only works on child processes, and Firecracker is no child of the pytest process (it is daemonized, for starters). The reason we never caught this being broken is because the test also simply ignores all exceptions raised. But there's more issues here: The test never caused _killed to be set to `True`, so if Firecracker really did exit, then we would have been seeing intermittent failures during microvm teardown (as Microvm.kill() asserts that the process is still alive if _killed is False). In fact, our guest kernels do not have the required drivers compiled in to support CTRL+ALT+DEL (thanks Riccardo for figuring this part out). Signed-off-by: Patrick Roy --- tests/integration_tests/functional/test_api.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index b21e86e0d60..eb2cd1b608e 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -767,24 +767,14 @@ def test_send_ctrl_alt_del(uvm_plain_any): test_microvm.spawn() test_microvm.basic_config() + test_microvm.add_net_iface() test_microvm.start() - # Wait around for the guest to boot up and initialize the user space - time.sleep(2) - test_microvm.api.actions.put(action_type="SendCtrlAltDel") - firecracker_pid = test_microvm.firecracker_pid - # If everything goes as expected, the guest OS will issue a reboot, # causing Firecracker to exit. - # waitpid should block until the Firecracker process has exited. If - # it has already exited by the time we call waitpid, WNOHANG causes - # waitpid to raise a ChildProcessError exception. - try: - os.waitpid(firecracker_pid, os.WNOHANG) - except ChildProcessError: - pass + test_microvm.mark_killed() def _drive_patch(test_microvm, io_engine): From 73564b735eaa97bda319411cbe2028198356431b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 12 Mar 2025 16:52:48 +0000 Subject: [PATCH 335/464] fix: drop i8042.nopnp argument from default kernel cmdline Since Firecracker gained ACPI support, disabling the ACPI probing of the keyboard device caused the CTRL+DEL+ALT functionality to no longer work unless the user explicitly modified the default kernel command lines in the PUT /machine-config endpoint. Restore pre-ACPI behavior of not needing to do this by dropping this parameter from the default set. Signed-off-by: Patrick Roy --- src/vmm/src/vmm_config/boot_source.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/vmm_config/boot_source.rs b/src/vmm/src/vmm_config/boot_source.rs index d62338fc94b..37ba08be449 100644 --- a/src/vmm/src/vmm_config/boot_source.rs +++ b/src/vmm/src/vmm_config/boot_source.rs @@ -14,10 +14,9 @@ use serde::{Deserialize, Serialize}; /// - `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.nopnp` do not use ACPIPnP to discover KBD/AUX controllers (save boot time); /// - `i8042.dumbkbd` do not attempt to control kbd state via the i8042 (save boot time). -pub const DEFAULT_KERNEL_CMDLINE: &str = "reboot=k panic=1 pci=off nomodule 8250.nr_uarts=0 \ - i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd"; +pub const DEFAULT_KERNEL_CMDLINE: &str = + "reboot=k panic=1 pci=off nomodule 8250.nr_uarts=0 i8042.noaux i8042.nomux i8042.dumbkbd"; /// Strongly typed data structure used to configure the boot source of the /// microvm. From 91cea5ebc0c9b742b6959bc70f9ba26a7cbdd390 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 13 Mar 2025 16:47:02 +0000 Subject: [PATCH 336/464] doc: add changelog entry about fixing CTRL+ALT+DEL add a changelog entry to let people know we fixed it Signed-off-by: Patrick Roy --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 965c763e524..b904f448b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,11 @@ and this project adheres to ### Fixed +- #\[[5074](https://github.com/firecracker-microvm/firecracker/pull/5074)\] Fix + the `SendCtrlAltDel` command not working for ACPI-enabled guest kernels, by + dropping the i8042.nopnp argument from the default kernel command line + Firecracker constructs. + ## [1.11.0] ### Added From a6491d82a5604e94536dc8f014943104cccab05a Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 11:22:03 +0000 Subject: [PATCH 337/464] chore(devctr): use poetry.group.dev.dependencies The section has been renamed and the old name has been deprecated. This has no functional changes. > The "poetry.dev-dependencies" section is deprecated and will > be removed in a future version. > Use "poetry.group.dev.dependencies" instead. Signed-off-by: Riccardo Mancini --- tools/devctr/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devctr/pyproject.toml b/tools/devctr/pyproject.toml index a4f7178aa5d..a2660a1fe59 100644 --- a/tools/devctr/pyproject.toml +++ b/tools/devctr/pyproject.toml @@ -35,7 +35,7 @@ setproctitle = "^1.3.2" tenacity = "^8.2.2" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] [build-system] requires = ["poetry-core>=1.0.0"] From fc4483f98a6642571fb8df8ac1d14c3867c31ff7 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 11:24:05 +0000 Subject: [PATCH 338/464] chore(devctr): update poetry lock file I've run `poetry update --lock` inside `/tools/devctr`. Signed-off-by: Riccardo Mancini --- tools/devctr/poetry.lock | 1465 +++++++++++++++++++++----------------- 1 file changed, 797 insertions(+), 668 deletions(-) diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock index b04d05efac9..b0ed4ce0f3b 100644 --- a/tools/devctr/poetry.lock +++ b/tools/devctr/poetry.lock @@ -1,99 +1,106 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" -version = "2.4.4" +version = "2.6.1" description = "Happy Eyeballs for asyncio" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, - {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, + {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"}, + {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"}, ] [[package]] name = "aiohttp" -version = "3.11.10" +version = "3.11.13" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" -files = [ - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d"}, - {file = "aiohttp-3.11.10-cp310-cp310-win32.whl", hash = "sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91"}, - {file = "aiohttp-3.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"}, - {file = "aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4"}, - {file = "aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc"}, - {file = "aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985"}, - {file = "aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836"}, - {file = "aiohttp-3.11.10-cp313-cp313-win32.whl", hash = "sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c"}, - {file = "aiohttp-3.11.10-cp313-cp313-win_amd64.whl", hash = "sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4"}, - {file = "aiohttp-3.11.10-cp39-cp39-win32.whl", hash = "sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be"}, - {file = "aiohttp-3.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74"}, - {file = "aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e"}, +groups = ["main"] +files = [ + {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"}, + {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"}, + {file = "aiohttp-3.11.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9840be675de208d1f68f84d578eaa4d1a36eee70b16ae31ab933520c49ba1325"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28a772757c9067e2aee8a6b2b425d0efaa628c264d6416d283694c3d86da7689"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b88aca5adbf4625e11118df45acac29616b425833c3be7a05ef63a6a4017bfdb"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce10ddfbe26ed5856d6902162f71b8fe08545380570a885b4ab56aecfdcb07f4"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa48dac27f41b36735c807d1ab093a8386701bbf00eb6b89a0f69d9fa26b3671"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89ce611b1eac93ce2ade68f1470889e0173d606de20c85a012bfa24be96cf867"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78e4dd9c34ec7b8b121854eb5342bac8b02aa03075ae8618b6210a06bbb8a115"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:66047eacbc73e6fe2462b77ce39fc170ab51235caf331e735eae91c95e6a11e4"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ad8f1c19fe277eeb8bc45741c6d60ddd11d705c12a4d8ee17546acff98e0802"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64815c6f02e8506b10113ddbc6b196f58dbef135751cc7c32136df27b736db09"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:967b93f21b426f23ca37329230d5bd122f25516ae2f24a9cea95a30023ff8283"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf1f31f83d16ec344136359001c5e871915c6ab685a3d8dee38e2961b4c81730"}, + {file = "aiohttp-3.11.13-cp310-cp310-win32.whl", hash = "sha256:00c8ac69e259c60976aa2edae3f13d9991cf079aaa4d3cd5a49168ae3748dee3"}, + {file = "aiohttp-3.11.13-cp310-cp310-win_amd64.whl", hash = "sha256:90d571c98d19a8b6e793b34aa4df4cee1e8fe2862d65cc49185a3a3d0a1a3996"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b35aab22419ba45f8fc290d0010898de7a6ad131e468ffa3922b1b0b24e9d2e"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81cba651db8795f688c589dd11a4fbb834f2e59bbf9bb50908be36e416dc760"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f55d0f242c2d1fcdf802c8fabcff25a9d85550a4cf3a9cf5f2a6b5742c992839"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bea08a6aad9195ac9b1be6b0c7e8a702a9cec57ce6b713698b4a5afa9c2e33"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6070bcf2173a7146bb9e4735b3c62b2accba459a6eae44deea0eb23e0035a23"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:718d5deb678bc4b9d575bfe83a59270861417da071ab44542d0fcb6faa686636"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f6b2c5b4a4d22b8fb2c92ac98e0747f5f195e8e9448bfb7404cd77e7bfa243f"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747ec46290107a490d21fe1ff4183bef8022b848cf9516970cb31de6d9460088"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01816f07c9cc9d80f858615b1365f8319d6a5fd079cd668cc58e15aafbc76a54"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a08ad95fcbd595803e0c4280671d808eb170a64ca3f2980dd38e7a72ed8d1fea"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c97be90d70f7db3aa041d720bfb95f4869d6063fcdf2bb8333764d97e319b7d0"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ab915a57c65f7a29353c8014ac4be685c8e4a19e792a79fe133a8e101111438e"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:35cda4e07f5e058a723436c4d2b7ba2124ab4e0aa49e6325aed5896507a8a42e"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af55314407714fe77a68a9ccaab90fdb5deb57342585fd4a3a8102b6d4370080"}, + {file = "aiohttp-3.11.13-cp311-cp311-win32.whl", hash = "sha256:42d689a5c0a0c357018993e471893e939f555e302313d5c61dfc566c2cad6185"}, + {file = "aiohttp-3.11.13-cp311-cp311-win_amd64.whl", hash = "sha256:b73a2b139782a07658fbf170fe4bcdf70fc597fae5ffe75e5b67674c27434a9f"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637"}, + {file = "aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee"}, + {file = "aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b"}, + {file = "aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c"}, + {file = "aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:51c3ff9c7a25f3cad5c09d9aacbc5aefb9267167c4652c1eb737989b554fe278"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e271beb2b1dabec5cd84eb488bdabf9758d22ad13471e9c356be07ad139b3012"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e9eb7e5764abcb49f0e2bd8f5731849b8728efbf26d0cac8e81384c95acec3f"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baae005092e3f200de02699314ac8933ec20abf998ec0be39448f6605bce93df"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1982c98ac62c132d2b773d50e2fcc941eb0b8bad3ec078ce7e7877c4d5a2dce7"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2b25b2eeb35707113b2d570cadc7c612a57f1c5d3e7bb2b13870fe284e08fc0"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b27961d65639128336b7a7c3f0046dcc62a9443d5ef962e3c84170ac620cec47"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe9f1e05025eacdd97590895e2737b9f851d0eb2e017ae9574d9a4f0b6252"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa1fb1b61881c8405829c50e9cc5c875bfdbf685edf57a76817dfb50643e4a1a"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:25de43bb3cf83ad83efc8295af7310219af6dbe4c543c2e74988d8e9c8a2a917"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe7065e2215e4bba63dc00db9ae654c1ba3950a5fff691475a32f511142fcddb"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7836587eef675a17d835ec3d98a8c9acdbeb2c1d72b0556f0edf4e855a25e9c1"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:85fa0b18558eb1427090912bd456a01f71edab0872f4e0f9e4285571941e4090"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a86dc177eb4c286c19d1823ac296299f59ed8106c9536d2b559f65836e0fb2c6"}, + {file = "aiohttp-3.11.13-cp39-cp39-win32.whl", hash = "sha256:684eea71ab6e8ade86b9021bb62af4bf0881f6be4e926b6b5455de74e420783a"}, + {file = "aiohttp-3.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:82c249f2bfa5ecbe4a1a7902c81c0fba52ed9ebd0176ab3047395d02ad96cfcb"}, + {file = "aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb"}, ] [package.dependencies] @@ -111,13 +118,14 @@ speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] [[package]] name = "aiosignal" -version = "1.3.1" +version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, + {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, + {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, ] [package.dependencies] @@ -129,6 +137,7 @@ version = "1.2.3" description = "Better dates & times for Python" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "arrow-1.2.3-py3-none-any.whl", hash = "sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"}, {file = "arrow-1.2.3.tar.gz", hash = "sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1"}, @@ -139,13 +148,14 @@ python-dateutil = ">=2.7.0" [[package]] name = "astroid" -version = "3.3.6" +version = "3.3.9" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.9.0" +groups = ["main"] files = [ - {file = "astroid-3.3.6-py3-none-any.whl", hash = "sha256:db676dc4f3ae6bfe31cda227dc60e03438378d7a896aec57422c95634e8d722f"}, - {file = "astroid-3.3.6.tar.gz", hash = "sha256:6aaea045f938c735ead292204afdb977a36e989522b7833ef6fea94de743f442"}, + {file = "astroid-3.3.9-py3-none-any.whl", hash = "sha256:d05bfd0acba96a7bd43e222828b7d9bc1e138aaeb0649707908d3702a9831248"}, + {file = "astroid-3.3.9.tar.gz", hash = "sha256:622cc8e3048684aa42c820d9d218978021c3c3d174fb03a9f0d615921744f550"}, ] [package.dependencies] @@ -157,6 +167,7 @@ version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, @@ -172,6 +183,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -179,32 +192,34 @@ files = [ [[package]] name = "attrs" -version = "24.2.0" +version = "25.2.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, + {file = "attrs-25.2.0-py3-none-any.whl", hash = "sha256:611344ff0a5fed735d86d7784610c84f8126b95e549bcad9ff61b4242f2d386b"}, + {file = "attrs-25.2.0.tar.gz", hash = "sha256:18a06db706db43ac232cce80443fcd9f2500702059ecf53489e3c5a3f417acaf"}, ] [package.extras] benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "aws-embedded-metrics" -version = "3.2.0" +version = "3.3.0" description = "AWS Embedded Metrics Package" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "aws-embedded-metrics-3.2.0.tar.gz", hash = "sha256:f235f87ab25ff328f6f3afca1c6b3218e81eea6e96e6aee012d368bb813fae7b"}, - {file = "aws_embedded_metrics-3.2.0-py3-none-any.whl", hash = "sha256:887b76d24914efa5fc42a7b77983e77fc670633e6e1195aac7653c425fee7399"}, + {file = "aws-embedded-metrics-3.3.0.tar.gz", hash = "sha256:f417c396b394959f923d5b53cfe241d01a0ccded60c8f30d9231ff05c8235ec5"}, + {file = "aws_embedded_metrics-3.3.0-py3-none-any.whl", hash = "sha256:03901a28786a93e718ddb7342a917c3a3c8204c31195edb36151d8b7eef361b3"}, ] [package.dependencies] @@ -216,6 +231,7 @@ version = "24.10.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, @@ -258,127 +274,116 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2024.8.30" +version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, + {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, + {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, ] [[package]] name = "charset-normalizer" -version = "3.4.0" +version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, - {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, - {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] @@ -387,6 +392,7 @@ version = "8.1.3" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, @@ -401,6 +407,8 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main"] +markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -408,13 +416,14 @@ files = [ [[package]] name = "decorator" -version = "5.1.1" +version = "5.2.1" description = "Decorators for Humans" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, + {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, + {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, ] [[package]] @@ -423,6 +432,7 @@ version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, @@ -438,6 +448,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -452,6 +464,7 @@ version = "2.1.1" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -462,13 +475,14 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "executing" -version = "2.1.0" +version = "2.2.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, - {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, + {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, + {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, ] [package.extras] @@ -476,18 +490,19 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "filelock" -version = "3.16.1" +version = "3.17.0" description = "A platform independent file lock." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, - {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, + {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, + {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] @@ -496,6 +511,7 @@ version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -597,6 +613,7 @@ version = "0.19.1" description = "Git commit message linter written in python, checks your commit messages for style." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "gitlint-0.19.1-py3-none-any.whl", hash = "sha256:26bb085959148d99fbbc178b4e56fda6c3edd7646b7c2a24d8ee1f8e036ed85d"}, {file = "gitlint-0.19.1.tar.gz", hash = "sha256:b5b70fb894e80849b69abbb65ee7dbb3520fc3511f202a6e6b6ddf1a71ee8f61"}, @@ -611,6 +628,7 @@ version = "0.19.1" description = "Git commit message linter written in python, checks your commit messages for style." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "gitlint_core-0.19.1-py3-none-any.whl", hash = "sha256:f41effd1dcbc06ffbfc56b6888cce72241796f517b46bd9fd4ab1b145056988c"}, {file = "gitlint_core-0.19.1.tar.gz", hash = "sha256:7bf977b03ff581624a9e03f65ebb8502cc12dfaa3e92d23e8b2b54bbdaa29992"}, @@ -639,6 +657,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -653,6 +672,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -660,13 +680,14 @@ files = [ [[package]] name = "ipython" -version = "8.30.0" +version = "8.34.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ - {file = "ipython-8.30.0-py3-none-any.whl", hash = "sha256:85ec56a7e20f6c38fce7727dcca699ae4ffc85985aa7b23635a8008f918ae321"}, - {file = "ipython-8.30.0.tar.gz", hash = "sha256:cb0a405a306d2995a5cbb9901894d240784a9f341394c6ba3f4fe8c6eb89ff6e"}, + {file = "ipython-8.34.0-py3-none-any.whl", hash = "sha256:0419883fa46e0baa182c5d50ebb8d6b49df1889fdb70750ad6d8cfe678eda6e3"}, + {file = "ipython-8.34.0.tar.gz", hash = "sha256:c31d658e754673ecc6514583e7dda8069e47136eb62458816b7d1e6625948b5a"}, ] [package.dependencies] @@ -702,6 +723,7 @@ version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" +groups = ["main"] files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, @@ -716,6 +738,7 @@ version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, @@ -735,6 +758,7 @@ version = "4.23.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, @@ -752,30 +776,32 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-path" -version = "0.3.3" +version = "0.3.4" description = "JSONSchema Spec with object-oriented paths" optional = false python-versions = "<4.0.0,>=3.8.0" +groups = ["main"] files = [ - {file = "jsonschema_path-0.3.3-py3-none-any.whl", hash = "sha256:203aff257f8038cd3c67be614fe6b2001043408cb1b4e36576bc4921e09d83c4"}, - {file = "jsonschema_path-0.3.3.tar.gz", hash = "sha256:f02e5481a4288ec062f8e68c808569e427d905bedfecb7f2e4c69ef77957c382"}, + {file = "jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8"}, + {file = "jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001"}, ] [package.dependencies] pathable = ">=0.4.1,<0.5.0" PyYAML = ">=5.1" -referencing = ">=0.28.0,<0.36.0" +referencing = "<0.37.0" requests = ">=2.31.0,<3.0.0" [[package]] name = "jsonschema-specifications" -version = "2023.12.1" +version = "2024.10.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, + {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, + {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, ] [package.dependencies] @@ -787,6 +813,7 @@ version = "1.10.0" description = "A fast and thorough lazy object proxy." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, @@ -833,6 +860,7 @@ version = "2.0.3" description = "Links recognition library with FULL unicode support." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048"}, {file = "linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79"}, @@ -853,6 +881,7 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -878,6 +907,7 @@ version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, @@ -892,6 +922,7 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -899,13 +930,14 @@ files = [ [[package]] name = "mdformat" -version = "0.7.19" +version = "0.7.22" description = "CommonMark compliant Markdown formatter" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "mdformat-0.7.19-py3-none-any.whl", hash = "sha256:5c360992adc118cf1479cbbe92bb3bd66dcd7f1a5a3a2ad6675915622c678cf1"}, - {file = "mdformat-0.7.19.tar.gz", hash = "sha256:a7d22df9802383432367864da907d2d147485b5cb6872e2d66937c1333e4d58a"}, + {file = "mdformat-0.7.22-py3-none-any.whl", hash = "sha256:61122637c9e1d9be1329054f3fa216559f0d1f722b7919b060a8c2a4ae1850e5"}, + {file = "mdformat-0.7.22.tar.gz", hash = "sha256:eef84fa8f233d3162734683c2a8a6222227a229b9206872e6139658d99acb1ea"}, ] [package.dependencies] @@ -918,6 +950,7 @@ version = "0.1.1" description = "An mdformat plugin for parsing/validating footnotes" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "mdformat_footnote-0.1.1-py3-none-any.whl", hash = "sha256:30063aaa0f74c36257c2e80fa0cf00d7c71a5277f27e98109e8765ae8678a95b"}, {file = "mdformat_footnote-0.1.1.tar.gz", hash = "sha256:3b85c4c84119f15f0b651df89c99a4f6f119fc46dca6b33f7edf4f09655d1126"}, @@ -937,6 +970,7 @@ version = "2.0.8" description = "An mdformat plugin for parsing / ignoring frontmatter." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "mdformat_frontmatter-2.0.8-py3-none-any.whl", hash = "sha256:577396695af96ad66dff1ff781284ff3764a10be3ab8659f2ef842ab42264ebb"}, {file = "mdformat_frontmatter-2.0.8.tar.gz", hash = "sha256:c11190ae3f9c91ada78fbd820f5b221631b520484e0b644715aa0f6ed7f097ed"}, @@ -957,6 +991,7 @@ version = "0.3.7" description = "Mdformat plugin for GitHub Flavored Markdown compatibility" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "mdformat_gfm-0.3.7-py3-none-any.whl", hash = "sha256:c40966ef26e334226961ab77908dc9697ed63668f6383a18c80cca1cb4bb5c10"}, {file = "mdformat_gfm-0.3.7.tar.gz", hash = "sha256:7deb2cd1d5334541af5454e52e116639796fc441ddc08e4415f967955950fe10"}, @@ -974,6 +1009,7 @@ version = "1.0.0" description = "An mdformat plugin for rendering tables." optional = false python-versions = ">=3.7.0" +groups = ["main"] files = [ {file = "mdformat_tables-1.0.0-py3-none-any.whl", hash = "sha256:94cd86126141b2adc3b04c08d1441eb1272b36c39146bab078249a41c7240a9a"}, {file = "mdformat_tables-1.0.0.tar.gz", hash = "sha256:a57db1ac17c4a125da794ef45539904bb8a9592e80557d525e1f169c96daa2c8"}, @@ -992,6 +1028,7 @@ version = "0.4.2" description = "Collection of plugins for markdown-it-py" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, @@ -1011,6 +1048,7 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -1022,6 +1060,7 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -1126,6 +1165,7 @@ version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -1133,82 +1173,84 @@ files = [ [[package]] name = "numpy" -version = "2.2.0" +version = "2.2.3" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" -files = [ - {file = "numpy-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e25507d85da11ff5066269d0bd25d06e0a0f2e908415534f3e603d2a78e4ffa"}, - {file = "numpy-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a62eb442011776e4036af5c8b1a00b706c5bc02dc15eb5344b0c750428c94219"}, - {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:b606b1aaf802e6468c2608c65ff7ece53eae1a6874b3765f69b8ceb20c5fa78e"}, - {file = "numpy-2.2.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:36b2b43146f646642b425dd2027730f99bac962618ec2052932157e213a040e9"}, - {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fe8f3583e0607ad4e43a954e35c1748b553bfe9fdac8635c02058023277d1b3"}, - {file = "numpy-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:122fd2fcfafdefc889c64ad99c228d5a1f9692c3a83f56c292618a59aa60ae83"}, - {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f2f5cddeaa4424a0a118924b988746db6ffa8565e5829b1841a8a3bd73eb59a"}, - {file = "numpy-2.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fe4bb0695fe986a9e4deec3b6857003b4cfe5c5e4aac0b95f6a658c14635e31"}, - {file = "numpy-2.2.0-cp310-cp310-win32.whl", hash = "sha256:b30042fe92dbd79f1ba7f6898fada10bdaad1847c44f2dff9a16147e00a93661"}, - {file = "numpy-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dc1d6d66f8d37843ed281773c7174f03bf7ad826523f73435deb88ba60d2d4"}, - {file = "numpy-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9874bc2ff574c40ab7a5cbb7464bf9b045d617e36754a7bc93f933d52bd9ffc6"}, - {file = "numpy-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0da8495970f6b101ddd0c38ace92edea30e7e12b9a926b57f5fabb1ecc25bb90"}, - {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0557eebc699c1c34cccdd8c3778c9294e8196df27d713706895edc6f57d29608"}, - {file = "numpy-2.2.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:3579eaeb5e07f3ded59298ce22b65f877a86ba8e9fe701f5576c99bb17c283da"}, - {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40deb10198bbaa531509aad0cd2f9fadb26c8b94070831e2208e7df543562b74"}, - {file = "numpy-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2aed8fcf8abc3020d6a9ccb31dbc9e7d7819c56a348cc88fd44be269b37427e"}, - {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a222d764352c773aa5ebde02dd84dba3279c81c6db2e482d62a3fa54e5ece69b"}, - {file = "numpy-2.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4e58666988605e251d42c2818c7d3d8991555381be26399303053b58a5bbf30d"}, - {file = "numpy-2.2.0-cp311-cp311-win32.whl", hash = "sha256:4723a50e1523e1de4fccd1b9a6dcea750c2102461e9a02b2ac55ffeae09a4410"}, - {file = "numpy-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:16757cf28621e43e252c560d25b15f18a2f11da94fea344bf26c599b9cf54b73"}, - {file = "numpy-2.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3"}, - {file = "numpy-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e"}, - {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67"}, - {file = "numpy-2.2.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e"}, - {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038"}, - {file = "numpy-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03"}, - {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a"}, - {file = "numpy-2.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef"}, - {file = "numpy-2.2.0-cp312-cp312-win32.whl", hash = "sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1"}, - {file = "numpy-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3"}, - {file = "numpy-2.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367"}, - {file = "numpy-2.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae"}, - {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69"}, - {file = "numpy-2.2.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13"}, - {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671"}, - {file = "numpy-2.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571"}, - {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d"}, - {file = "numpy-2.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742"}, - {file = "numpy-2.2.0-cp313-cp313-win32.whl", hash = "sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e"}, - {file = "numpy-2.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2"}, - {file = "numpy-2.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95"}, - {file = "numpy-2.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c"}, - {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca"}, - {file = "numpy-2.2.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d"}, - {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529"}, - {file = "numpy-2.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3"}, - {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab"}, - {file = "numpy-2.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72"}, - {file = "numpy-2.2.0-cp313-cp313t-win32.whl", hash = "sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066"}, - {file = "numpy-2.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881"}, - {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e12c6c1ce84628c52d6367863773f7c8c8241be554e8b79686e91a43f1733773"}, - {file = "numpy-2.2.0-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:b6207dc8fb3c8cb5668e885cef9ec7f70189bec4e276f0ff70d5aa078d32c88e"}, - {file = "numpy-2.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a50aeff71d0f97b6450d33940c7181b08be1441c6c193e678211bff11aa725e7"}, - {file = "numpy-2.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:df12a1f99b99f569a7c2ae59aa2d31724e8d835fc7f33e14f4792e3071d11221"}, - {file = "numpy-2.2.0.tar.gz", hash = "sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0"}, +groups = ["main"] +files = [ + {file = "numpy-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cbc6472e01952d3d1b2772b720428f8b90e2deea8344e854df22b0618e9cce71"}, + {file = "numpy-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdfe0c22692a30cd830c0755746473ae66c4a8f2e7bd508b35fb3b6a0813d787"}, + {file = "numpy-2.2.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:e37242f5324ffd9f7ba5acf96d774f9276aa62a966c0bad8dae692deebec7716"}, + {file = "numpy-2.2.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:95172a21038c9b423e68be78fd0be6e1b97674cde269b76fe269a5dfa6fadf0b"}, + {file = "numpy-2.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b47c440210c5d1d67e1cf434124e0b5c395eee1f5806fdd89b553ed1acd0a3"}, + {file = "numpy-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0391ea3622f5c51a2e29708877d56e3d276827ac5447d7f45e9bc4ade8923c52"}, + {file = "numpy-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f6b3dfc7661f8842babd8ea07e9897fe3d9b69a1d7e5fbb743e4160f9387833b"}, + {file = "numpy-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1ad78ce7f18ce4e7df1b2ea4019b5817a2f6a8a16e34ff2775f646adce0a5027"}, + {file = "numpy-2.2.3-cp310-cp310-win32.whl", hash = "sha256:5ebeb7ef54a7be11044c33a17b2624abe4307a75893c001a4800857956b41094"}, + {file = "numpy-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:596140185c7fa113563c67c2e894eabe0daea18cf8e33851738c19f70ce86aeb"}, + {file = "numpy-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8"}, + {file = "numpy-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b"}, + {file = "numpy-2.2.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a"}, + {file = "numpy-2.2.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636"}, + {file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d"}, + {file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb"}, + {file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2"}, + {file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b"}, + {file = "numpy-2.2.3-cp311-cp311-win32.whl", hash = "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5"}, + {file = "numpy-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f"}, + {file = "numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d"}, + {file = "numpy-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95"}, + {file = "numpy-2.2.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea"}, + {file = "numpy-2.2.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532"}, + {file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e"}, + {file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe"}, + {file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021"}, + {file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8"}, + {file = "numpy-2.2.3-cp312-cp312-win32.whl", hash = "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe"}, + {file = "numpy-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d"}, + {file = "numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba"}, + {file = "numpy-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50"}, + {file = "numpy-2.2.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1"}, + {file = "numpy-2.2.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5"}, + {file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2"}, + {file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1"}, + {file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304"}, + {file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d"}, + {file = "numpy-2.2.3-cp313-cp313-win32.whl", hash = "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693"}, + {file = "numpy-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b"}, + {file = "numpy-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890"}, + {file = "numpy-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c"}, + {file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94"}, + {file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0"}, + {file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610"}, + {file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76"}, + {file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a"}, + {file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf"}, + {file = "numpy-2.2.3-cp313-cp313t-win32.whl", hash = "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef"}, + {file = "numpy-2.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082"}, + {file = "numpy-2.2.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3c2ec8a0f51d60f1e9c0c5ab116b7fc104b165ada3f6c58abf881cb2eb16044d"}, + {file = "numpy-2.2.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:ed2cf9ed4e8ebc3b754d398cba12f24359f018b416c380f577bbae112ca52fc9"}, + {file = "numpy-2.2.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39261798d208c3095ae4f7bc8eaeb3481ea8c6e03dc48028057d3cbdbdb8937e"}, + {file = "numpy-2.2.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:783145835458e60fa97afac25d511d00a1eca94d4a8f3ace9fe2043003c678e4"}, + {file = "numpy-2.2.3.tar.gz", hash = "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020"}, ] [[package]] name = "openapi-schema-validator" -version = "0.6.2" +version = "0.6.3" description = "OpenAPI schema validation for Python" optional = false -python-versions = ">=3.8.0,<4.0.0" +python-versions = "<4.0.0,>=3.8.0" +groups = ["main"] files = [ - {file = "openapi_schema_validator-0.6.2-py3-none-any.whl", hash = "sha256:c4887c1347c669eb7cded9090f4438b710845cd0f90d1fb9e1b3303fb37339f8"}, - {file = "openapi_schema_validator-0.6.2.tar.gz", hash = "sha256:11a95c9c9017912964e3e5f2545a5b11c3814880681fcacfb73b1759bb4f2804"}, + {file = "openapi_schema_validator-0.6.3-py3-none-any.whl", hash = "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3"}, + {file = "openapi_schema_validator-0.6.3.tar.gz", hash = "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee"}, ] [package.dependencies] jsonschema = ">=4.19.1,<5.0.0" -jsonschema-specifications = ">=2023.5.2,<2024.0.0" +jsonschema-specifications = ">=2023.5.2" rfc3339-validator = "*" [[package]] @@ -1217,6 +1259,7 @@ version = "0.7.1" description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3 spec validator" optional = false python-versions = ">=3.8.0,<4.0.0" +groups = ["main"] files = [ {file = "openapi_spec_validator-0.7.1-py3-none-any.whl", hash = "sha256:3c81825043f24ccbcd2f4b149b11e8231abce5ba84f37065e14ec947d8f4e959"}, {file = "openapi_spec_validator-0.7.1.tar.gz", hash = "sha256:8577b85a8268685da6f8aa30990b83b7960d4d1117e901d451b5d572605e5ec7"}, @@ -1234,6 +1277,7 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -1245,6 +1289,7 @@ version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -1256,13 +1301,14 @@ testing = ["docopt", "pytest"] [[package]] name = "pathable" -version = "0.4.3" +version = "0.4.4" description = "Object-oriented paths" optional = false -python-versions = ">=3.7.0,<4.0.0" +python-versions = "<4.0.0,>=3.7.0" +groups = ["main"] files = [ - {file = "pathable-0.4.3-py3-none-any.whl", hash = "sha256:cdd7b1f9d7d5c8b8d3315dbf5a86b2596053ae845f056f57d97c0eefff84da14"}, - {file = "pathable-0.4.3.tar.gz", hash = "sha256:5c869d315be50776cc8a993f3af43e0c60dc01506b399643f919034ebf4cdcab"}, + {file = "pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2"}, + {file = "pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2"}, ] [[package]] @@ -1271,6 +1317,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -1282,6 +1329,8 @@ version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -1296,6 +1345,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1312,6 +1362,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1323,13 +1374,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.48" +version = "3.0.50" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" +groups = ["main"] files = [ - {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, - {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, + {file = "prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198"}, + {file = "prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab"}, ] [package.dependencies] @@ -1337,123 +1389,141 @@ wcwidth = "*" [[package]] name = "propcache" -version = "0.2.1" +version = "0.3.0" description = "Accelerated property cache" optional = false python-versions = ">=3.9" -files = [ - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, - {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, - {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, - {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, - {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, - {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, - {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, - {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, - {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, - {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, - {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, - {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, - {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, +groups = ["main"] +files = [ + {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d"}, + {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c"}, + {file = "propcache-0.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f"}, + {file = "propcache-0.3.0-cp310-cp310-win32.whl", hash = "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c"}, + {file = "propcache-0.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c"}, + {file = "propcache-0.3.0-cp311-cp311-win32.whl", hash = "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d"}, + {file = "propcache-0.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c"}, + {file = "propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d"}, + {file = "propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626"}, + {file = "propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374"}, + {file = "propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf"}, + {file = "propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863"}, + {file = "propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f"}, + {file = "propcache-0.3.0-cp39-cp39-win32.whl", hash = "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663"}, + {file = "propcache-0.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929"}, + {file = "propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043"}, + {file = "propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5"}, ] [[package]] name = "psutil" -version = "6.1.0" +version = "6.1.1" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, - {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, - {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, - {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, - {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, - {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, - {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, - {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, +groups = ["main"] +files = [ + {file = "psutil-6.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8"}, + {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777"}, + {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8df0178ba8a9e5bc84fed9cfa61d54601b371fbec5c8eebad27575f1e105c0d4"}, + {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:1924e659d6c19c647e763e78670a05dbb7feaf44a0e9c94bf9e14dfc6ba50468"}, + {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:018aeae2af92d943fdf1da6b58665124897cfc94faa2ca92098838f83e1b1bca"}, + {file = "psutil-6.1.1-cp27-none-win32.whl", hash = "sha256:6d4281f5bbca041e2292be3380ec56a9413b790579b8e593b1784499d0005dac"}, + {file = "psutil-6.1.1-cp27-none-win_amd64.whl", hash = "sha256:c777eb75bb33c47377c9af68f30e9f11bc78e0f07fbf907be4a5d70b2fe5f030"}, + {file = "psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8"}, + {file = "psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377"}, + {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003"}, + {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160"}, + {file = "psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3"}, + {file = "psutil-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:384636b1a64b47814437d1173be1427a7c83681b17a450bfc309a1953e329603"}, + {file = "psutil-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8be07491f6ebe1a693f17d4f11e69d0dc1811fa082736500f649f79df7735303"}, + {file = "psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53"}, + {file = "psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649"}, + {file = "psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5"}, ] [package.extras] -dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] +dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"] test = ["pytest", "pytest-xdist", "setuptools"] [[package]] @@ -1462,6 +1532,8 @@ version = "0.7.0" description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -1473,6 +1545,7 @@ version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, @@ -1483,13 +1556,14 @@ tests = ["pytest"] [[package]] name = "pygments" -version = "2.18.0" +version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, ] [package.extras] @@ -1497,24 +1571,25 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "3.3.2" +version = "3.3.5" description = "python code static checker" optional = false python-versions = ">=3.9.0" +groups = ["main"] files = [ - {file = "pylint-3.3.2-py3-none-any.whl", hash = "sha256:77f068c287d49b8683cd7c6e624243c74f92890f767f106ffa1ddf3c0a54cb7a"}, - {file = "pylint-3.3.2.tar.gz", hash = "sha256:9ec054ec992cd05ad30a6df1676229739a73f8feeabf3912c995d17601052b01"}, + {file = "pylint-3.3.5-py3-none-any.whl", hash = "sha256:7cb170929a371238530b2eeea09f5f28236d106b70308c3d46a9c0cf11634633"}, + {file = "pylint-3.3.5.tar.gz", hash = "sha256:38d0f784644ed493d91f76b5333a0e370a1c1bc97c22068a77523b4bf1e82c31"}, ] [package.dependencies] -astroid = ">=3.3.5,<=3.4.0-dev0" +astroid = ">=3.3.8,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] -isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +isort = ">=4.2.5,<5.13.0 || >5.13.0,<7" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -1526,13 +1601,14 @@ testutils = ["gitpython (>3)"] [[package]] name = "pytest" -version = "8.3.4" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, - {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] @@ -1552,6 +1628,7 @@ version = "1.5.0" description = "A pytest plugin to report test results as JSON files" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pytest-json-report-1.5.0.tar.gz", hash = "sha256:2dde3c647851a19b5f3700729e8310a6e66efb2077d674f27ddea3d34dc615de"}, {file = "pytest_json_report-1.5.0-py3-none-any.whl", hash = "sha256:9897b68c910b12a2e48dd849f9a284b2c79a732a8a9cb398452ddd23d3c8c325"}, @@ -1567,6 +1644,7 @@ version = "3.1.1" description = "pytest plugin for test session metadata" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pytest_metadata-3.1.1-py3-none-any.whl", hash = "sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b"}, {file = "pytest_metadata-3.1.1.tar.gz", hash = "sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8"}, @@ -1584,6 +1662,7 @@ version = "14.0" description = "pytest plugin to re-run tests to eliminate flaky failures" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pytest-rerunfailures-14.0.tar.gz", hash = "sha256:4a400bcbcd3c7a4ad151ab8afac123d90eca3abe27f98725dc4d9702887d2e92"}, {file = "pytest_rerunfailures-14.0-py3-none-any.whl", hash = "sha256:4197bdd2eaeffdbf50b5ea6e7236f47ff0e44d1def8dae08e409f536d84e7b32"}, @@ -1599,6 +1678,7 @@ version = "2.3.1" description = "pytest plugin to abort hanging tests" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "pytest-timeout-2.3.1.tar.gz", hash = "sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9"}, {file = "pytest_timeout-2.3.1-py3-none-any.whl", hash = "sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e"}, @@ -1613,6 +1693,7 @@ version = "3.6.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, @@ -1633,6 +1714,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1647,6 +1729,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1705,18 +1788,20 @@ files = [ [[package]] name = "referencing" -version = "0.35.1" +version = "0.36.2" description = "JSON Referencing + Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, - {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, + {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, + {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "requests" @@ -1724,6 +1809,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -1745,6 +1831,7 @@ version = "0.4.2" description = "Use requests to talk HTTP via a UNIX domain socket" optional = false python-versions = "<4.0.0,>=3.8.1" +groups = ["main"] files = [ {file = "requests_unixsocket2-0.4.2-py3-none-any.whl", hash = "sha256:701fcd49d74bc0f759bbe45c4dfda0045fd89652948c2b473b1a312214c3770b"}, {file = "requests_unixsocket2-0.4.2.tar.gz", hash = "sha256:929c58ecc5981f3d127661ceb9ec8c76e0f08d31c52e44ab1462ac0dcd55b5f5"}, @@ -1760,6 +1847,7 @@ version = "0.1.4" description = "A pure python RFC3339 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] files = [ {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, @@ -1770,125 +1858,127 @@ six = "*" [[package]] name = "rpds-py" -version = "0.22.3" +version = "0.23.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" -files = [ - {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, - {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, - {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, - {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, - {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, - {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, - {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, - {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, - {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, - {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, - {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, - {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, - {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, +groups = ["main"] +files = [ + {file = "rpds_py-0.23.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2a54027554ce9b129fc3d633c92fa33b30de9f08bc61b32c053dc9b537266fed"}, + {file = "rpds_py-0.23.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b5ef909a37e9738d146519657a1aab4584018746a18f71c692f2f22168ece40c"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ee9d6f0b38efb22ad94c3b68ffebe4c47865cdf4b17f6806d6c674e1feb4246"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7356a6da0562190558c4fcc14f0281db191cdf4cb96e7604c06acfcee96df15"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9441af1d25aed96901f97ad83d5c3e35e6cd21a25ca5e4916c82d7dd0490a4fa"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d8abf7896a91fb97e7977d1aadfcc2c80415d6dc2f1d0fca5b8d0df247248f3"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b08027489ba8fedde72ddd233a5ea411b85a6ed78175f40285bd401bde7466d"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fee513135b5a58f3bb6d89e48326cd5aa308e4bcdf2f7d59f67c861ada482bf8"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:35d5631ce0af26318dba0ae0ac941c534453e42f569011585cb323b7774502a5"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a20cb698c4a59c534c6701b1c24a968ff2768b18ea2991f886bd8985ce17a89f"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e9c206a1abc27e0588cf8b7c8246e51f1a16a103734f7750830a1ccb63f557a"}, + {file = "rpds_py-0.23.1-cp310-cp310-win32.whl", hash = "sha256:d9f75a06ecc68f159d5d7603b734e1ff6daa9497a929150f794013aa9f6e3f12"}, + {file = "rpds_py-0.23.1-cp310-cp310-win_amd64.whl", hash = "sha256:f35eff113ad430b5272bbfc18ba111c66ff525828f24898b4e146eb479a2cdda"}, + {file = "rpds_py-0.23.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b79f5ced71efd70414a9a80bbbfaa7160da307723166f09b69773153bf17c590"}, + {file = "rpds_py-0.23.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9e799dac1ffbe7b10c1fd42fe4cd51371a549c6e108249bde9cd1200e8f59b4"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721f9c4011b443b6e84505fc00cc7aadc9d1743f1c988e4c89353e19c4a968ee"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f88626e3f5e57432e6191cd0c5d6d6b319b635e70b40be2ffba713053e5147dd"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:285019078537949cecd0190f3690a0b0125ff743d6a53dfeb7a4e6787af154f5"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92f5654157de1379c509b15acec9d12ecf6e3bc1996571b6cb82a4302060447"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e768267cbe051dd8d1c5305ba690bb153204a09bf2e3de3ae530de955f5b5580"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5334a71f7dc1160382d45997e29f2637c02f8a26af41073189d79b95d3321f1"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6adb81564af0cd428910f83fa7da46ce9ad47c56c0b22b50872bc4515d91966"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cafa48f2133d4daa028473ede7d81cd1b9f9e6925e9e4003ebdf77010ee02f35"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fced9fd4a07a1ded1bac7e961ddd9753dd5d8b755ba8e05acba54a21f5f1522"}, + {file = "rpds_py-0.23.1-cp311-cp311-win32.whl", hash = "sha256:243241c95174b5fb7204c04595852fe3943cc41f47aa14c3828bc18cd9d3b2d6"}, + {file = "rpds_py-0.23.1-cp311-cp311-win_amd64.whl", hash = "sha256:11dd60b2ffddba85715d8a66bb39b95ddbe389ad2cfcf42c833f1bcde0878eaf"}, + {file = "rpds_py-0.23.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c"}, + {file = "rpds_py-0.23.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad"}, + {file = "rpds_py-0.23.1-cp312-cp312-win32.whl", hash = "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057"}, + {file = "rpds_py-0.23.1-cp312-cp312-win_amd64.whl", hash = "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165"}, + {file = "rpds_py-0.23.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935"}, + {file = "rpds_py-0.23.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93"}, + {file = "rpds_py-0.23.1-cp313-cp313-win32.whl", hash = "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd"}, + {file = "rpds_py-0.23.1-cp313-cp313-win_amd64.whl", hash = "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70"}, + {file = "rpds_py-0.23.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731"}, + {file = "rpds_py-0.23.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5"}, + {file = "rpds_py-0.23.1-cp313-cp313t-win32.whl", hash = "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7"}, + {file = "rpds_py-0.23.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d"}, + {file = "rpds_py-0.23.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:09cd7dbcb673eb60518231e02874df66ec1296c01a4fcd733875755c02014b19"}, + {file = "rpds_py-0.23.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6760211eee3a76316cf328f5a8bd695b47b1626d21c8a27fb3b2473a884d597"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72e680c1518733b73c994361e4b06441b92e973ef7d9449feec72e8ee4f713da"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae28144c1daa61366205d32abd8c90372790ff79fc60c1a8ad7fd3c8553a600e"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c698d123ce5d8f2d0cd17f73336615f6a2e3bdcedac07a1291bb4d8e7d82a05a"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98b257ae1e83f81fb947a363a274c4eb66640212516becaff7bef09a5dceacaa"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c9ff044eb07c8468594d12602291c635da292308c8c619244e30698e7fc455a"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7938c7b0599a05246d704b3f5e01be91a93b411d0d6cc62275f025293b8a11ce"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e9cb79ecedfc156c0692257ac7ed415243b6c35dd969baa461a6888fc79f2f07"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7b77e07233925bd33fc0022b8537774423e4c6680b6436316c5075e79b6384f4"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a970bfaf130c29a679b1d0a6e0f867483cea455ab1535fb427566a475078f27f"}, + {file = "rpds_py-0.23.1-cp39-cp39-win32.whl", hash = "sha256:4233df01a250b3984465faed12ad472f035b7cd5240ea3f7c76b7a7016084495"}, + {file = "rpds_py-0.23.1-cp39-cp39-win_amd64.whl", hash = "sha256:c617d7453a80e29d9973b926983b1e700a9377dbe021faa36041c78537d7b08c"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c1f8afa346ccd59e4e5630d5abb67aba6a9812fddf764fd7eb11f382a345f8cc"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fad784a31869747df4ac968a351e070c06ca377549e4ace94775aaa3ab33ee06"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a96fcac2f18e5a0a23a75cd27ce2656c66c11c127b0318e508aab436b77428"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e77febf227a1dc3220159355dba68faa13f8dca9335d97504abf428469fb18b"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26bb3e8de93443d55e2e748e9fd87deb5f8075ca7bc0502cfc8be8687d69a2ec"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db7707dde9143a67b8812c7e66aeb2d843fe33cc8e374170f4d2c50bd8f2472d"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eedaaccc9bb66581d4ae7c50e15856e335e57ef2734dbc5fd8ba3e2a4ab3cb6"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28358c54fffadf0ae893f6c1050e8f8853e45df22483b7fff2f6ab6152f5d8bf"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:633462ef7e61d839171bf206551d5ab42b30b71cac8f10a64a662536e057fdef"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a98f510d86f689fcb486dc59e6e363af04151e5260ad1bdddb5625c10f1e95f8"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e0397dd0b3955c61ef9b22838144aa4bef6f0796ba5cc8edfc64d468b93798b4"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:75307599f0d25bf6937248e5ac4e3bde5ea72ae6618623b86146ccc7845ed00b"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3614d280bf7aab0d3721b5ce0e73434acb90a2c993121b6e81a1c15c665298ac"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e5963ea87f88bddf7edd59644a35a0feecf75f8985430124c253612d4f7d27ae"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad76f44f70aac3a54ceb1813ca630c53415da3a24fd93c570b2dfb4856591017"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c6ae11e6e93728d86aafc51ced98b1658a0080a7dd9417d24bfb955bb09c3c2"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc869af5cba24d45fb0399b0cfdbcefcf6910bf4dee5d74036a57cf5264b3ff4"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c76b32eb2ab650a29e423525e84eb197c45504b1c1e6e17b6cc91fcfeb1a4b1d"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4263320ed887ed843f85beba67f8b2d1483b5947f2dc73a8b068924558bfeace"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f9682a8f71acdf59fd554b82b1c12f517118ee72c0f3944eda461606dfe7eb9"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:754fba3084b70162a6b91efceee8a3f06b19e43dac3f71841662053c0584209a"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:a1c66e71ecfd2a4acf0e4bd75e7a3605afa8f9b28a3b497e4ba962719df2be57"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8d67beb6002441faef8251c45e24994de32c4c8686f7356a1f601ad7c466f7c3"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a1e17d8dc8e57d8e0fd21f8f0f0a5211b3fa258b2e444c2053471ef93fe25a00"}, + {file = "rpds_py-0.23.1.tar.gz", hash = "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707"}, ] [[package]] name = "ruamel-yaml" -version = "0.18.6" +version = "0.18.10" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ - {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, - {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, + {file = "ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1"}, + {file = "ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58"}, ] [package.dependencies] @@ -1904,6 +1994,8 @@ version = "0.2.12" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\"" files = [ {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, @@ -1911,6 +2003,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, + {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, @@ -1919,6 +2012,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, + {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, @@ -1927,6 +2021,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, + {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, @@ -1935,6 +2030,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, + {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, @@ -1943,6 +2039,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, + {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, @@ -1950,146 +2047,161 @@ files = [ [[package]] name = "scipy" -version = "1.14.1" +version = "1.15.2" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.10" -files = [ - {file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"}, - {file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"}, - {file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"}, - {file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"}, - {file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"}, - {file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"}, - {file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"}, - {file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"}, - {file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"}, - {file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"}, - {file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"}, - {file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"}, - {file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"}, - {file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"}, - {file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"}, - {file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"}, - {file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"}, - {file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"}, - {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"}, - {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"}, - {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"}, - {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"}, - {file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"}, - {file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"}, - {file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"}, - {file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"}, - {file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"}, - {file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"}, - {file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"}, - {file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"}, - {file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"}, - {file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"}, - {file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"}, +groups = ["main"] +files = [ + {file = "scipy-1.15.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9"}, + {file = "scipy-1.15.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5"}, + {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e"}, + {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9"}, + {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3"}, + {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d"}, + {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58"}, + {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa"}, + {file = "scipy-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65"}, + {file = "scipy-1.15.2-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4"}, + {file = "scipy-1.15.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1"}, + {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971"}, + {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655"}, + {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e"}, + {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0"}, + {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40"}, + {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462"}, + {file = "scipy-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737"}, + {file = "scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd"}, + {file = "scipy-1.15.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301"}, + {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93"}, + {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20"}, + {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e"}, + {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8"}, + {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11"}, + {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53"}, + {file = "scipy-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded"}, + {file = "scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf"}, + {file = "scipy-1.15.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37"}, + {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d"}, + {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb"}, + {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27"}, + {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0"}, + {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32"}, + {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d"}, + {file = "scipy-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f"}, + {file = "scipy-1.15.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9"}, + {file = "scipy-1.15.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f"}, + {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6"}, + {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af"}, + {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274"}, + {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776"}, + {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828"}, + {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28"}, + {file = "scipy-1.15.2-cp313-cp313t-win_amd64.whl", hash = "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db"}, + {file = "scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec"}, ] [package.dependencies] -numpy = ">=1.23.5,<2.3" +numpy = ">=1.23.5,<2.5" [package.extras] dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] -doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"] -test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.16.5)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"] +test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "setproctitle" -version = "1.3.4" +version = "1.3.5" description = "A Python module to customize the process title" optional = false python-versions = ">=3.8" -files = [ - {file = "setproctitle-1.3.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0f6661a69c68349172ba7b4d5dd65fec2b0917abc99002425ad78c3e58cf7595"}, - {file = "setproctitle-1.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:754bac5e470adac7f7ec2239c485cd0b75f8197ca8a5b86ffb20eb3a3676cc42"}, - {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7bc7088c15150745baf66db62a4ced4507d44419eb66207b609f91b64a682af"}, - {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a46ef3ecf61e4840fbc1145fdd38acf158d0da7543eda7b773ed2b30f75c2830"}, - {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcb09d5c0ffa043254ec9a734a73f3791fec8bf6333592f906bb2e91ed2af1a"}, - {file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06c16b7a91cdc5d700271899e4383384a61aae83a3d53d0e2e5a266376083342"}, - {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9f9732e59863eaeedd3feef94b2b216cb86d40dda4fad2d0f0aaec3b31592716"}, - {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e152f4ab9ea1632b5fecdd87cee354f2b2eb6e2dfc3aceb0eb36a01c1e12f94c"}, - {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:020ea47a79b2bbd7bd7b94b85ca956ba7cb026e82f41b20d2e1dac4008cead25"}, - {file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c52b12b10e4057fc302bd09cb3e3f28bb382c30c044eb3396e805179a8260e4"}, - {file = "setproctitle-1.3.4-cp310-cp310-win32.whl", hash = "sha256:a65a147f545f3fac86f11acb2d0b316d3e78139a9372317b7eb50561b2817ba0"}, - {file = "setproctitle-1.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:66821fada6426998762a3650a37fba77e814a249a95b1183011070744aff47f6"}, - {file = "setproctitle-1.3.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0f749f07002c2d6fecf37cedc43207a88e6c651926a470a5f229070cf791879"}, - {file = "setproctitle-1.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90ea8d302a5d30b948451d146e94674a3c5b020cc0ced9a1c28f8ddb0f203a5d"}, - {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f859c88193ed466bee4eb9d45fbc29d2253e6aa3ccd9119c9a1d8d95f409a60d"}, - {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3afa5a0ed08a477ded239c05db14c19af585975194a00adf594d48533b23701"}, - {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a78fce9018cc3e9a772b6537bbe3fe92380acf656c9f86db2f45e685af376e"}, - {file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d758e2eed2643afac5f2881542fbb5aa97640b54be20d0a5ed0691d02f0867d"}, - {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ef133a1a2ee378d549048a12d56f4ef0e2b9113b0b25b6b77821e9af94d50634"}, - {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d2a154b79d5fb42d1eff06e05e22f0e8091261d877dd47b37d31352b74ecc37"}, - {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:202eae632815571297833876a0f407d0d9c7ad9d843b38adbe687fe68c5192ee"}, - {file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2b0080819859e80a7776ac47cf6accb4b7ad313baf55fabac89c000480dcd103"}, - {file = "setproctitle-1.3.4-cp311-cp311-win32.whl", hash = "sha256:9c9d7d1267dee8c6627963d9376efa068858cfc8f573c083b1b6a2d297a8710f"}, - {file = "setproctitle-1.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:475986ddf6df65d619acd52188336a20f616589403f5a5ceb3fc70cdc137037a"}, - {file = "setproctitle-1.3.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d06990dcfcd41bb3543c18dd25c8476fbfe1f236757f42fef560f6aa03ac8dfc"}, - {file = "setproctitle-1.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:317218c9d8b17a010ab2d2f0851e8ef584077a38b1ba2b7c55c9e44e79a61e73"}, - {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5fefb53b9d9f334a5d9ec518a36b92a10b936011ac8a6b6dffd60135f16459"}, - {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0855006261635e8669646c7c304b494b6df0a194d2626683520103153ad63cc9"}, - {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a88e466fcaee659679c1d64dcb2eddbcb4bfadffeb68ba834d9c173a25b6184"}, - {file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f963b6ed8ba33eda374a98d979e8a0eaf21f891b6e334701693a2c9510613c4c"}, - {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:122c2e05697fa91f5d23f00bbe98a9da1bd457b32529192e934095fadb0853f1"}, - {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1bba0a866f5895d5b769d8c36b161271c7fd407e5065862ab80ff91c29fbe554"}, - {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97f1f861998e326e640708488c442519ad69046374b2c3fe9bcc9869b387f23c"}, - {file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:726aee40357d4bdb70115442cb85ccc8e8bc554fc0bbbaa3a57cbe81df42287d"}, - {file = "setproctitle-1.3.4-cp312-cp312-win32.whl", hash = "sha256:04d6ba8b816dbb0bfd62000b0c3e583160893e6e8c4233e1dca1a9ae4d95d924"}, - {file = "setproctitle-1.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:9c76e43cb351ba8887371240b599925cdf3ecececc5dfb7125c71678e7722c55"}, - {file = "setproctitle-1.3.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6e3b177e634aa6bbbfbf66d097b6d1cdb80fc60e912c7d8bace2e45699c07dd"}, - {file = "setproctitle-1.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6b17655a5f245b416e127e02087ea6347a48821cc4626bc0fd57101bfcd88afc"}, - {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa5057a86df920faab8ee83960b724bace01a3231eb8e3f2c93d78283504d598"}, - {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149fdfb8a26a555780c4ce53c92e6d3c990ef7b30f90a675eca02e83c6d5f76d"}, - {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ded03546938a987f463c68ab98d683af87a83db7ac8093bbc179e77680be5ba2"}, - {file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ab9f5b7f2bbc1754bc6292d9a7312071058e5a891b0391e6d13b226133f36aa"}, - {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0b19813c852566fa031902124336fa1f080c51e262fc90266a8c3d65ca47b74c"}, - {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db78b645dc63c0ccffca367a498f3b13492fb106a2243a1e998303ba79c996e2"}, - {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b669aaac70bd9f03c070270b953f78d9ee56c4af6f0ff9f9cd3e6d1878c10b40"}, - {file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6dc3d656702791565994e64035a208be56b065675a5bc87b644c657d6d9e2232"}, - {file = "setproctitle-1.3.4-cp313-cp313-win32.whl", hash = "sha256:091f682809a4d12291cf0205517619d2e7014986b7b00ebecfde3d76f8ae5a8f"}, - {file = "setproctitle-1.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:adcd6ba863a315702184d92d3d3bbff290514f24a14695d310f02ae5e28bd1f7"}, - {file = "setproctitle-1.3.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:acf41cf91bbc5a36d1fa4455a818bb02bf2a4ccfed2f892ba166ba2fcbb0ec8a"}, - {file = "setproctitle-1.3.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ceb3ce3262b0e8e088e4117175591b7a82b3bdc5e52e33b1e74778b5fb53fd38"}, - {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2ef636a6a25fe7f3d5a064bea0116b74a4c8c7df9646b17dc7386c439a26cf"}, - {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28b8614de08679ae95bc4e8d6daaef6b61afdf027fa0d23bf13d619000286b3c"}, - {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24f3c8be826a7d44181eac2269b15b748b76d98cd9a539d4c69f09321dcb5c12"}, - {file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9d79b1bf833af63b7c720a6604eb16453ac1ad4e718eb8b59d1f97d986b98c"}, - {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fb693000b65842c85356b667d057ae0d0bac6519feca7e1c437cc2cfeb0afc59"}, - {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a166251b8fbc6f2755e2ce9d3c11e9edb0c0c7d2ed723658ff0161fbce26ac1c"}, - {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:0361428e6378911a378841509c56ba472d991cbed1a7e3078ec0cacc103da44a"}, - {file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:62d66e0423e3bd520b4c897063506b309843a8d07343fbfad04197e91a4edd28"}, - {file = "setproctitle-1.3.4-cp38-cp38-win32.whl", hash = "sha256:5edd01909348f3b0b2da329836d6b5419cd4869fec2e118e8ff3275b38af6267"}, - {file = "setproctitle-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:59e0dda9ad245921af0328035a961767026e1fa94bb65957ab0db0a0491325d6"}, - {file = "setproctitle-1.3.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bdaaa81a6e95a0a19fba0285f10577377f3503ae4e9988b403feba79da3e2f80"}, - {file = "setproctitle-1.3.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ee5b19a2d794463bcc19153dfceede7beec784b4cf7967dec0bc0fc212ab3a3"}, - {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3058a1bb0c767b3a6ccbb38b27ef870af819923eb732e21e44a3f300370fe159"}, - {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a97d37ee4fe0d1c6e87d2a97229c27a88787a8f4ebfbdeee95f91b818e52efe"}, - {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e61dd7d05da11fc69bb86d51f1e0ee08f74dccf3ecf884c94de41135ffdc75d"}, - {file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb115d53dc2a1299ae72f1119c96a556db36073bacb6da40c47ece5db0d9587"}, - {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:342570716e2647a51ea859b8a9126da9dc1a96a0153c9c0a3514effd60ab57ad"}, - {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ad212ae2b03951367a69584af034579b34e1e4199a75d377ef9f8e08ee299b1"}, - {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4afcb38e22122465013f4621b7e9ff8d42a7a48ae0ffeb94133a806cb91b4aad"}, - {file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:30bb223e6c3f95ad9e9bb2a113292759e947d1cfd60dbd4adb55851c370006b2"}, - {file = "setproctitle-1.3.4-cp39-cp39-win32.whl", hash = "sha256:5f0521ed3bb9f02e9486573ea95e2062cd6bf036fa44e640bd54a06f22d85f35"}, - {file = "setproctitle-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:0baadeb27f9e97e65922b4151f818b19c311d30b9efdb62af0e53b3db4006ce2"}, - {file = "setproctitle-1.3.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:939d364a187b2adfbf6ae488664277e717d56c7951a4ddeb4f23b281bc50bfe5"}, - {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb8a6a19be0cbf6da6fcbf3698b76c8af03fe83e4bd77c96c3922be3b88bf7da"}, - {file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779006f9e1aade9522a40e8d9635115ab15dd82b7af8e655967162e9c01e2573"}, - {file = "setproctitle-1.3.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5519f2a7b8c535b0f1f77b30441476571373add72008230c81211ee17b423b57"}, - {file = "setproctitle-1.3.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:743836d484151334ebba1490d6907ca9e718fe815dcd5756f2a01bc3067d099c"}, - {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abda20aff8d1751e48d7967fa8945fef38536b82366c49be39b83678d4be3893"}, - {file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a2041b5788ce52f218b5be94af458e04470f997ab46fdebd57cf0b8374cc20e"}, - {file = "setproctitle-1.3.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2c3b1ce68746557aa6e6f4547e76883925cdc7f8d7c7a9f518acd203f1265ca5"}, - {file = "setproctitle-1.3.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0b6a4cbabf024cb263a45bdef425760f14470247ff223f0ec51699ca9046c0fe"}, - {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e55d7ecc68bdc80de5a553691a3ed260395d5362c19a266cf83cbb4e046551f"}, - {file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02ca3802902d91a89957f79da3ec44b25b5804c88026362cb85eea7c1fbdefd1"}, - {file = "setproctitle-1.3.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:47669fc8ed8b27baa2d698104732234b5389f6a59c37c046f6bcbf9150f7a94e"}, - {file = "setproctitle-1.3.4.tar.gz", hash = "sha256:3b40d32a3e1f04e94231ed6dfee0da9e43b4f9c6b5450d53e6dd7754c34e0c50"}, +groups = ["main"] +files = [ + {file = "setproctitle-1.3.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02870e0cb0de7f68a7a8a5b23c2bc0ce63821cab3d9b126f9be80bb6cd674c80"}, + {file = "setproctitle-1.3.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:55b278135be742b8901067479626d909f6613bd2d2c4fd0de6bb46f80e07a919"}, + {file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53fc971f7bf7a674f571a23cdec70f2f0ac88152c59c06aa0808d0be6d834046"}, + {file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb0500e1bc6f00b8ba696c3743ddff14c8679e3c2ca9d292c008ac51488d17cf"}, + {file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:995b3ac1b5fe510f4e1d1c19ebf19f4bceb448f2d6e8d99ea23f33cb6f1a277e"}, + {file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a05e2c3fdfbda32b9c9da72d0506398d1efb5bd2c5981b9e12d3622eb3d4f9"}, + {file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:310c7f4ca4c8476a9840b2cd4b22ee602a49a3c902fdcd2dd8284685abd10a9a"}, + {file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:867af4a5c3d85484fbcc50ea88bcd375acf709cff88a3259575361849c0da351"}, + {file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8ec0a7fe9f1ba90900144489bc93ce7dd4dec3f3df1e7f188c9e58364fe4a4c5"}, + {file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:aaee7acba2733a14a886488b7495bfec4a8d6407124c04a0946dbde1684230a3"}, + {file = "setproctitle-1.3.5-cp310-cp310-win32.whl", hash = "sha256:bd2cccd972e4282af4ce2c13cd9ebdf07be157eabafd8ce648fffdc8ae6fbe28"}, + {file = "setproctitle-1.3.5-cp310-cp310-win_amd64.whl", hash = "sha256:81f2328ac34c9584e1e5f87eea916c0bc48476a06606a07debae07acdd7ab5ea"}, + {file = "setproctitle-1.3.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1c8dcc250872385f2780a5ea58050b58cbc8b6a7e8444952a5a65c359886c593"}, + {file = "setproctitle-1.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ca82fae9eb4800231dd20229f06e8919787135a5581da245b8b05e864f34cc8b"}, + {file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0424e1d33232322541cb36fb279ea5242203cd6f20de7b4fb2a11973d8e8c2ce"}, + {file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fec8340ab543144d04a9d805d80a0aad73fdeb54bea6ff94e70d39a676ea4ec0"}, + {file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eab441c89f181271ab749077dcc94045a423e51f2fb0b120a1463ef9820a08d0"}, + {file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c371550a2288901a0dcd84192691ebd3197a43c95f3e0b396ed6d1cedf5c6c"}, + {file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:78288ff5f9c415c56595b2257ad218936dd9fa726b36341b373b31ca958590fe"}, + {file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f1f13a25fc46731acab518602bb1149bfd8b5fabedf8290a7c0926d61414769d"}, + {file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1534d6cd3854d035e40bf4c091984cbdd4d555d7579676d406c53c8f187c006f"}, + {file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62a01c76708daac78b9688ffb95268c57cb57fa90b543043cda01358912fe2db"}, + {file = "setproctitle-1.3.5-cp311-cp311-win32.whl", hash = "sha256:ea07f29735d839eaed985990a0ec42c8aecefe8050da89fec35533d146a7826d"}, + {file = "setproctitle-1.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:ab3ae11e10d13d514d4a5a15b4f619341142ba3e18da48c40e8614c5a1b5e3c3"}, + {file = "setproctitle-1.3.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:523424b9be4dea97d95b8a584b183f35c7bab2d0a3d995b01febf5b8a8de90e4"}, + {file = "setproctitle-1.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b6ec1d86c1b4d7b5f2bdceadf213310cf24696b82480a2a702194b8a0bfbcb47"}, + {file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea6c505264275a43e9b2acd2acfc11ac33caf52bc3167c9fced4418a810f6b1c"}, + {file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b91e68e6685998e6353f296100ecabc313a6cb3e413d66a03d74b988b61f5ff"}, + {file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc1fda208ae3a2285ad27aeab44c41daf2328abe58fa3270157a739866779199"}, + {file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:828727d220e46f048b82289018300a64547b46aaed96bf8810c05fe105426b41"}, + {file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:83b016221cf80028b2947be20630faa14e3e72a403e35f0ba29550b4e856767b"}, + {file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6d8a411e752e794d052434139ca4234ffeceeb8d8d8ddc390a9051d7942b2726"}, + {file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50cfbf86b9c63a2c2903f1231f0a58edeb775e651ae1af84eec8430b0571f29b"}, + {file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f3b5e2eacd572444770026c9dd3ddc7543ce427cdf452d40a408d1e95beefb30"}, + {file = "setproctitle-1.3.5-cp312-cp312-win32.whl", hash = "sha256:cf4e3ded98027de2596c6cc5bbd3302adfb3ca315c848f56516bb0b7e88de1e9"}, + {file = "setproctitle-1.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:f7a8c01ffd013dda2bed6e7d5cb59fbb609e72f805abf3ee98360f38f7758d9b"}, + {file = "setproctitle-1.3.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:162fd76781f57f42ddf27c475e5fef6a8df4fdd69b28dd554e53e2eb2bfe0f95"}, + {file = "setproctitle-1.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4969d996bdfbe23bbd023cd0bae6c73a27371615c4ec5296a60cecce268659ef"}, + {file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd70c95a94473216e7c7a7a1f7d8ecbaca5b16d4ba93ddbfd32050fc485a8451"}, + {file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a887582bfdb6dcbc482db0ef9e630ad23ca95875806ef2b444bf6fbd7b7d7ca"}, + {file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:755671c39a9e70834eeec6dc6b61e344399c49881d2e7ea3534a1c69669dd9cc"}, + {file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ab52b4c2ce056a1b60d439991a81ca90f019488d4b4f64b2779e6badd3677e6"}, + {file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36178b944019ec7fc52bb967ffeee296a11d373734a7be276755bedb3db5c141"}, + {file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:269d41cd4f085b69821d1ee6599124f02dbbc79962b256e260b6c9021d037994"}, + {file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d880630fd81d1b3bde121c352ca7ea2f2ff507ef40c3c011d0928ed491f912c9"}, + {file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8a7fed67ab49f60bd51f3b4cffff3f8d754d1bb0a40e42869911301ec6519b65"}, + {file = "setproctitle-1.3.5-cp313-cp313-win32.whl", hash = "sha256:e9c0d0cfcf715631b10d5950d04a9978f63bc46535724ef7c2eaf1dca9988642"}, + {file = "setproctitle-1.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:e1d28eb98c91fbebd3e443a45c7da5d84974959851ef304c330eabd654a386f1"}, + {file = "setproctitle-1.3.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8995a1217b52d11d92bafd069961a47c5e13d8751ca976a32b3ecbbd471eaf9b"}, + {file = "setproctitle-1.3.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae2ce64ea87837c4e3e65a7a232ff80cf09aa7d916e74cb34a245c47fcd87981"}, + {file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b84de1780bbb0adc67560a113a0ea57e6ecfce2325680de8efe6c2a2f781ac"}, + {file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b1d2628ac9868f960d7e87b3a9b2bb337104c3644b699e52e01efd7e106e4fe"}, + {file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa912c4d08c66afda30dd5af8f2e9c59065dfc36a51edbd5419c3a7c962875aa"}, + {file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4f783e100f8b451cd92fcabd3b831edfb1f7cb02be4a79b972f138e0001885"}, + {file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8ca56e39d10b6758046694a84950e5c5570a034c409ef3337595f64fc2cfa94d"}, + {file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8915d69260ba6a6aaf9a48f6b53dbf9f8e4dc0cb4ae25bc5edb16a1666b6e47c"}, + {file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7edd4fbb9fd17ed0e5a7f8bde9fa61c3987a34372084c45bab4eab6a2e554762"}, + {file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d0b19fd76d46b8096a463724739c3b09cf5ce38317f559f56f424f6ce7158de3"}, + {file = "setproctitle-1.3.5-cp38-cp38-win32.whl", hash = "sha256:53ce572cdbd43a0bed2aa24299cd823ebf233a7fa720cc7f8634728c213679c0"}, + {file = "setproctitle-1.3.5-cp38-cp38-win_amd64.whl", hash = "sha256:a58f00f35d6038ce1e8a9e5f87cb5ecce13ce118c5977a603566ad1fccc8d2cb"}, + {file = "setproctitle-1.3.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c4b299b5bbadf00034978b8d741c85af25173146747eb9dab22596ec805a52d6"}, + {file = "setproctitle-1.3.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d57e7626329d4fb138da5ce15270b08a91326969956fb19c7a8fec2639066704"}, + {file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4272295721cf1fd2acf960b674d6dc09bec87f2a1e48995817b4ec4a3d483faf"}, + {file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8305b6e6c203222c61318f338f1de08269ec66c247bf251593c215ff1fbeaf9"}, + {file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:becc9f3f605936506d2bd63d9cf817b7ee66b10d204184c4a633064dbed579d6"}, + {file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4629de80c47155a26e8d87a0a92d9428aa8d79ccfe2c20fd18888580619704e1"}, + {file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f1af1d310b5b6cda692da52bd862a9833086c0a3f8380fa92505dd23857dcf60"}, + {file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3bb6ea3d6e690677619508050bc681d86223723bdf67e4e8a8dffc3d04ca3044"}, + {file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:322067ef1ffe70d297b00bee8a3862fed96021aa4318e3bce2d7c3bfa7a8d1e7"}, + {file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1b58d49c32a46c48dcc2812635a89e6bee31139b03818da49a0bbaeaf01edef9"}, + {file = "setproctitle-1.3.5-cp39-cp39-win32.whl", hash = "sha256:707c23d4a88f5e66f1005d93558bf84eb45fc0fb0c4f33480a0c7d0895e8e848"}, + {file = "setproctitle-1.3.5-cp39-cp39-win_amd64.whl", hash = "sha256:c64199a73d442a06d372b5286942229a43e86fa41bf36f317dcc60c036aff0bb"}, + {file = "setproctitle-1.3.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dc66b84beb0d5eb03abf0c3140c6d2cbe3d67ae9f0824a09dfa8c6ff164319a6"}, + {file = "setproctitle-1.3.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31dc9b330e7cac7685bdef790747c07914081c11ee1066eb0c597303dfb52010"}, + {file = "setproctitle-1.3.5-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4028639b511f5e641d116b3b54ad70c637ebd1b4baac0948283daf11b104119f"}, + {file = "setproctitle-1.3.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6bddef4e27d0ed74e44b58bf050bc3108591bf17d20d461fc59cd141282f849c"}, + {file = "setproctitle-1.3.5-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:9996be1d1df399c3cdc6d72ce0064e46bc74fc6e29fe16a328511a303dd4d418"}, + {file = "setproctitle-1.3.5-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cefc2dbdc48121022c3c05644cd3706f08e0b3c0ce07814d3c04daba0617936"}, + {file = "setproctitle-1.3.5-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cef63879c79a570aabf7c158f453bf8d1285f0fda4b6b9b7a52d64b49c084d40"}, + {file = "setproctitle-1.3.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a863296a31fb578726c570314cb78ff3a3fddb65963dc01ea33731760f20a92c"}, + {file = "setproctitle-1.3.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b63bda3cb4b6526720dc7c6940b891c593f41771d119aeb8763875801ce2296d"}, + {file = "setproctitle-1.3.5-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95913af603da5b4c7635bf1fb67ecc5df7c18360b6cfb6740fd743bb150a6e17"}, + {file = "setproctitle-1.3.5-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b130cf8fe76dc05ad1d48cc9ff3699eb1f0d8edbf6f46a3ce46a7041e49d7b"}, + {file = "setproctitle-1.3.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe3bfd5e51c24349d022e062a96c316a1b8862ea9a0cf5ea2a8b2ae008b77cec"}, + {file = "setproctitle-1.3.5.tar.gz", hash = "sha256:1e6eaeaf8a734d428a95d8c104643b39af7d247d604f40a7bebcf3960a853c5e"}, ] [package.extras] @@ -2101,19 +2213,23 @@ version = "1.14.3" description = "Python subprocess replacement" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\"" files = [ {file = "sh-1.14.3.tar.gz", hash = "sha256:e4045b6c732d9ce75d571c79f5ac2234edd9ae4f5fa9d59b09705082bdca18c7"}, ] [[package]] name = "sh" -version = "2.1.0" +version = "2.2.2" description = "Python subprocess replacement" optional = false python-versions = "<4.0,>=3.8.1" +groups = ["main"] +markers = "" files = [ - {file = "sh-2.1.0-py3-none-any.whl", hash = "sha256:bf5e44178dd96a542126c2774e9b7ab1d89bfe0e2ef84d92e6d0ed7358d63d01"}, - {file = "sh-2.1.0.tar.gz", hash = "sha256:7e27301c574bec8ca5bf6f211851357526455ee97cd27a7c4c6cc5e2375399cb"}, + {file = "sh-2.2.2-py3-none-any.whl", hash = "sha256:e0b15b4ae8ffcd399bc8ffddcbd770a43c7a70a24b16773fbb34c001ad5d52af"}, + {file = "sh-2.2.2.tar.gz", hash = "sha256:653227a7c41a284ec5302173fbc044ee817c7bad5e6e4d8d55741b9aeb9eb65b"}, ] [[package]] @@ -2122,6 +2238,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -2133,6 +2250,7 @@ version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, @@ -2152,6 +2270,7 @@ version = "8.5.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, @@ -2167,6 +2286,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2208,6 +2329,7 @@ version = "0.13.2" description = "Style preserving TOML library" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, @@ -2219,6 +2341,7 @@ version = "5.14.3" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, @@ -2234,6 +2357,8 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version < \"3.13\"" files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -2245,6 +2370,7 @@ version = "1.0.3" description = "Micro subset of unicode data files for linkify-it-py projects." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a"}, {file = "uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5"}, @@ -2255,13 +2381,14 @@ test = ["coverage", "pytest", "pytest-cov"] [[package]] name = "urllib3" -version = "2.2.3" +version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, ] [package.extras] @@ -2276,6 +2403,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -2287,6 +2415,7 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, @@ -2378,6 +2507,6 @@ multidict = ">=4.0" propcache = ">=0.2.0" [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.10.0" -content-hash = "e38bfcb8811fb9b774956ed4b0e82603dbe5b66d8cb5bc4af6ed86417a9d5d1d" +content-hash = "b020499c9bfb8350e20d3426276ea2d2cfa530f8b5fcc7a23a2c07173beeacc7" From ced9dfa38bd44f279afc8dc575b01508c3ca9de0 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 11:24:53 +0000 Subject: [PATCH 339/464] chore(devctr): update rust toolchain to 1.85.0 This commit updates the rust toolchain in the devctr to 1.85.0. Changes will take effect on the next devctr release. Signed-off-by: Riccardo Mancini --- rust-toolchain.toml | 2 +- tools/devctr/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index af10d0da481..6bf302b6e1a 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.83.0" +channel = "1.85.0" targets = ["x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl"] profile = "minimal" diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index f855033fc4d..0448f2231dc 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.83.0" +ARG RUST_TOOLCHAIN="1.85.0" ARG TMP_BUILD_DIR=/tmp/build ARG DEBIAN_FRONTEND=noninteractive ARG PIP_BREAK_SYSTEM_PACKAGES=1 From 9099eac5128d51866136b04edab791edb4c46105 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:11:07 +0000 Subject: [PATCH 340/464] chore(clippy): fix "operator precedence can trip the unwary" The clippy update now flags cases where operator precedence may lead to unexpected results [1]. The fix is to explicitly wrap in parenthesis. [1]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence Signed-off-by: Riccardo Mancini --- src/acpi-tables/src/aml.rs | 30 ++++++------ src/vmm/src/acpi/mod.rs | 2 +- src/vmm/src/acpi/x86_64.rs | 6 +-- src/vmm/src/arch/x86_64/cpu_model.rs | 8 ++-- src/vmm/src/devices/virtio/device.rs | 2 +- src/vmm/src/devices/virtio/net/device.rs | 54 +++++++++++----------- src/vmm/src/devices/virtio/persist.rs | 2 +- src/vmm/src/devices/virtio/vsock/device.rs | 2 +- 8 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/acpi-tables/src/aml.rs b/src/acpi-tables/src/aml.rs index 69feb5b004f..2c391bda65e 100644 --- a/src/acpi-tables/src/aml.rs +++ b/src/acpi-tables/src/aml.rs @@ -265,12 +265,12 @@ impl EisaName { let data = name.as_bytes(); - let value: u32 = (u32::from(data[0] - 0x40) << 26 - | u32::from(data[1] - 0x40) << 21 - | u32::from(data[2] - 0x40) << 16 - | name.chars().nth(3).unwrap().to_digit(16).unwrap() << 12 - | name.chars().nth(4).unwrap().to_digit(16).unwrap() << 8 - | name.chars().nth(5).unwrap().to_digit(16).unwrap() << 4 + let value: u32 = ((u32::from(data[0] - 0x40) << 26) + | (u32::from(data[1] - 0x40) << 21) + | (u32::from(data[2] - 0x40) << 16) + | (name.chars().nth(3).unwrap().to_digit(16).unwrap() << 12) + | (name.chars().nth(4).unwrap().to_digit(16).unwrap() << 8) + | (name.chars().nth(5).unwrap().to_digit(16).unwrap() << 4) | name.chars().nth(6).unwrap().to_digit(16).unwrap()) .swap_bytes(); @@ -439,7 +439,7 @@ where r#type: AddressSpaceType::Memory, min, max, - type_flags: (cacheable as u8) << 1 | u8::from(read_write), + type_flags: ((cacheable as u8) << 1) | u8::from(read_write), }) } @@ -471,7 +471,7 @@ where bytes.push(descriptor); // Word Address Space Descriptor bytes.extend_from_slice(&(TryInto::::try_into(length).unwrap()).to_le_bytes()); bytes.push(self.r#type as u8); // type - let generic_flags = 1 << 2 /* Min Fixed */ | 1 << 3; // Max Fixed + let generic_flags = (1 << 2) /* Min Fixed */ | (1 << 3); // Max Fixed bytes.push(generic_flags); bytes.push(self.type_flags); } @@ -591,9 +591,9 @@ impl Aml for Interrupt { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { bytes.push(0x89); // Extended IRQ Descriptor bytes.extend_from_slice(&6u16.to_le_bytes()); - let flags = u8::from(self.shared) << 3 - | u8::from(self.active_low) << 2 - | u8::from(self.edge_triggered) << 1 + let flags = (u8::from(self.shared) << 3) + | (u8::from(self.active_low) << 2) + | (u8::from(self.edge_triggered) << 1) | u8::from(self.consumer); bytes.push(flags); bytes.push(1u8); // count @@ -682,7 +682,7 @@ impl Aml for Method<'_> { fn append_aml_bytes(&self, bytes: &mut Vec) -> Result<(), AmlError> { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; - let flags: u8 = (self.args & 0x7) | u8::from(self.serialized) << 3; + let flags: u8 = (self.args & 0x7) | (u8::from(self.serialized) << 3); tmp.push(flags); for child in &self.children { child.append_aml_bytes(&mut tmp)?; @@ -766,7 +766,7 @@ impl Aml for Field { let mut tmp = Vec::new(); self.path.append_aml_bytes(&mut tmp)?; - let flags: u8 = self.access_type as u8 | (self.update_rule as u8) << 5; + let flags: u8 = self.access_type as u8 | ((self.update_rule as u8) << 5); tmp.push(flags); for field in self.fields.iter() { @@ -1491,12 +1491,12 @@ mod tests { assert_eq!(create_pkg_length(&[0u8; 62], true), vec![63]); assert_eq!( create_pkg_length(&[0u8; 64], true), - vec![1 << 6 | (66 & 0xf), 66 >> 4] + vec![(1 << 6) | (66 & 0xf), 66 >> 4] ); assert_eq!( create_pkg_length(&[0u8; 4096], true), vec![ - 2 << 6 | (4099 & 0xf) as u8, + (2 << 6) | (4099 & 0xf) as u8, ((4099 >> 4) & 0xff).try_into().unwrap(), ((4099 >> 12) & 0xff).try_into().unwrap() ] diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index 9542fad3902..e89d259ed3a 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -105,7 +105,7 @@ impl AcpiTableWriter<'_> { fadt.set_hypervisor_vendor_id(HYPERVISOR_VENDOR_ID); fadt.set_x_dsdt(dsdt_addr); fadt.set_flags( - 1 << FADT_F_HW_REDUCED_ACPI | 1 << FADT_F_PWR_BUTTON | 1 << FADT_F_SLP_BUTTON, + (1 << FADT_F_HW_REDUCED_ACPI) | (1 << FADT_F_PWR_BUTTON) | (1 << FADT_F_SLP_BUTTON), ); setup_arch_fadt(&mut fadt); self.write_acpi_table(&mut fadt) diff --git a/src/vmm/src/acpi/x86_64.rs b/src/vmm/src/acpi/x86_64.rs index 7d2e9f0364a..d7328aecba9 100644 --- a/src/vmm/src/acpi/x86_64.rs +++ b/src/vmm/src/acpi/x86_64.rs @@ -34,9 +34,9 @@ pub(crate) fn setup_arch_fadt(fadt: &mut Fadt) { // More info here: // https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html?highlight=0a06#ia-pc-boot-architecture-flags fadt.setup_iapc_flags( - 1 << IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT - | 1 << IAPC_BOOT_ARG_FLAGS_PCI_ASPM - | 1 << IAPC_BOOT_ARG_FLAGS_MSI_NOT_PRESENT, + (1 << IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT) + | (1 << IAPC_BOOT_ARG_FLAGS_PCI_ASPM) + | (1 << IAPC_BOOT_ARG_FLAGS_MSI_NOT_PRESENT), ); } diff --git a/src/vmm/src/arch/x86_64/cpu_model.rs b/src/vmm/src/arch/x86_64/cpu_model.rs index befaa3953bf..fd3399a736f 100644 --- a/src/vmm/src/arch/x86_64/cpu_model.rs +++ b/src/vmm/src/arch/x86_64/cpu_model.rs @@ -56,10 +56,10 @@ impl From<&u32> for CpuModel { impl From<&CpuModel> for u32 { fn from(cpu_model: &CpuModel) -> Self { - u32::from(cpu_model.extended_family) << 20 - | u32::from(cpu_model.extended_model) << 16 - | u32::from(cpu_model.family) << 8 - | u32::from(cpu_model.model) << 4 + (u32::from(cpu_model.extended_family) << 20) + | (u32::from(cpu_model.extended_model) << 16) + | (u32::from(cpu_model.family) << 8) + | (u32::from(cpu_model.model) << 4) | u32::from(cpu_model.stepping) } } diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs index 5adf4873dc6..7e67bb0f189 100644 --- a/src/vmm/src/devices/virtio/device.rs +++ b/src/vmm/src/devices/virtio/device.rs @@ -104,7 +104,7 @@ pub trait VirtioDevice: AsAny + Send { /// Check if virtio device has negotiated given feature. fn has_feature(&self, feature: u64) -> bool { - (self.acked_features() & 1 << feature) != 0 + (self.acked_features() & (1 << feature)) != 0 } /// The virtio device type. diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 99941f5796a..3e984e4fc76 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -274,17 +274,17 @@ impl Net { rx_rate_limiter: RateLimiter, tx_rate_limiter: RateLimiter, ) -> Result { - let mut avail_features = 1 << VIRTIO_NET_F_GUEST_CSUM - | 1 << VIRTIO_NET_F_CSUM - | 1 << VIRTIO_NET_F_GUEST_TSO4 - | 1 << VIRTIO_NET_F_GUEST_TSO6 - | 1 << VIRTIO_NET_F_GUEST_UFO - | 1 << VIRTIO_NET_F_HOST_TSO4 - | 1 << VIRTIO_NET_F_HOST_TSO6 - | 1 << VIRTIO_NET_F_HOST_UFO - | 1 << VIRTIO_F_VERSION_1 - | 1 << VIRTIO_NET_F_MRG_RXBUF - | 1 << VIRTIO_RING_F_EVENT_IDX; + let mut avail_features = (1 << VIRTIO_NET_F_GUEST_CSUM) + | (1 << VIRTIO_NET_F_CSUM) + | (1 << VIRTIO_NET_F_GUEST_TSO4) + | (1 << VIRTIO_NET_F_GUEST_TSO6) + | (1 << VIRTIO_NET_F_GUEST_UFO) + | (1 << VIRTIO_NET_F_HOST_TSO4) + | (1 << VIRTIO_NET_F_HOST_TSO6) + | (1 << VIRTIO_NET_F_HOST_UFO) + | (1 << VIRTIO_F_VERSION_1) + | (1 << VIRTIO_NET_F_MRG_RXBUF) + | (1 << VIRTIO_RING_F_EVENT_IDX); let mut config_space = ConfigSpace::default(); if let Some(mac) = guest_mac { @@ -1115,18 +1115,18 @@ pub mod tests { set_mac(&mut net, MacAddr::from_str("11:22:33:44:55:66").unwrap()); // Test `features()` and `ack_features()`. - let features = 1 << VIRTIO_NET_F_GUEST_CSUM - | 1 << VIRTIO_NET_F_CSUM - | 1 << VIRTIO_NET_F_GUEST_TSO4 - | 1 << VIRTIO_NET_F_GUEST_TSO6 - | 1 << VIRTIO_NET_F_MAC - | 1 << VIRTIO_NET_F_GUEST_UFO - | 1 << VIRTIO_NET_F_HOST_TSO4 - | 1 << VIRTIO_NET_F_HOST_TSO6 - | 1 << VIRTIO_NET_F_HOST_UFO - | 1 << VIRTIO_F_VERSION_1 - | 1 << VIRTIO_NET_F_MRG_RXBUF - | 1 << VIRTIO_RING_F_EVENT_IDX; + let features = (1 << VIRTIO_NET_F_GUEST_CSUM) + | (1 << VIRTIO_NET_F_CSUM) + | (1 << VIRTIO_NET_F_GUEST_TSO4) + | (1 << VIRTIO_NET_F_GUEST_TSO6) + | (1 << VIRTIO_NET_F_MAC) + | (1 << VIRTIO_NET_F_GUEST_UFO) + | (1 << VIRTIO_NET_F_HOST_TSO4) + | (1 << VIRTIO_NET_F_HOST_TSO6) + | (1 << VIRTIO_NET_F_HOST_UFO) + | (1 << VIRTIO_F_VERSION_1) + | (1 << VIRTIO_NET_F_MRG_RXBUF) + | (1 << VIRTIO_RING_F_EVENT_IDX); assert_eq!( net.avail_features_by_page(0), @@ -1148,10 +1148,10 @@ pub mod tests { // Test that `Net::build_tap_offload_features` creates the TAP offload features that we expect // it to do, based on the available guest features fn test_build_tap_offload_features_all() { - let supported_features = 1 << VIRTIO_NET_F_GUEST_CSUM - | 1 << VIRTIO_NET_F_GUEST_UFO - | 1 << VIRTIO_NET_F_GUEST_TSO4 - | 1 << VIRTIO_NET_F_GUEST_TSO6; + let supported_features = (1 << VIRTIO_NET_F_GUEST_CSUM) + | (1 << VIRTIO_NET_F_GUEST_UFO) + | (1 << VIRTIO_NET_F_GUEST_TSO4) + | (1 << VIRTIO_NET_F_GUEST_TSO6); let expected_tap_features = gen::TUN_F_CSUM | gen::TUN_F_UFO | gen::TUN_F_TSO4 | gen::TUN_F_TSO6; let supported_flags = Net::build_tap_offload_features(supported_features); diff --git a/src/vmm/src/devices/virtio/persist.rs b/src/vmm/src/devices/virtio/persist.rs index 23293a25eab..d0938797f65 100644 --- a/src/vmm/src/devices/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/persist.rs @@ -160,7 +160,7 @@ impl VirtioDeviceState { return Err(PersistError::InvalidInput); } - let uses_notif_suppression = (self.acked_features & 1u64 << VIRTIO_RING_F_EVENT_IDX) != 0; + let uses_notif_suppression = (self.acked_features & (1u64 << VIRTIO_RING_F_EVENT_IDX)) != 0; let queue_construction_args = QueueConstructorArgs { mem: mem.clone(), is_activated: self.activated, diff --git a/src/vmm/src/devices/virtio/vsock/device.rs b/src/vmm/src/devices/virtio/vsock/device.rs index eb7c144c4be..ec0404bcd9a 100644 --- a/src/vmm/src/devices/virtio/vsock/device.rs +++ b/src/vmm/src/devices/virtio/vsock/device.rs @@ -49,7 +49,7 @@ pub(crate) const VIRTIO_VSOCK_EVENT_TRANSPORT_RESET: u32 = 0; /// - VIRTIO_F_IN_ORDER: the device returns used buffers in the same order that the driver makes /// them available. pub(crate) const AVAIL_FEATURES: u64 = - 1 << uapi::VIRTIO_F_VERSION_1 as u64 | 1 << uapi::VIRTIO_F_IN_ORDER as u64; + (1 << uapi::VIRTIO_F_VERSION_1 as u64) | (1 << uapi::VIRTIO_F_IN_ORDER as u64); /// Structure representing the vsock device. #[derive(Debug)] From b98ed6e9c3b3d7430befbcf1632191d16e71026f Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:14:55 +0000 Subject: [PATCH 341/464] chore(clippy): mark packed repr ABI explicit as C The rust toolchain version requires specifying which ABI the packed representation refers to [1]. In all our cases, we want C ABI. [1]: https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi Signed-off-by: Riccardo Mancini --- src/acpi-tables/src/fadt.rs | 2 +- src/acpi-tables/src/lib.rs | 4 ++-- src/acpi-tables/src/madt.rs | 6 +++--- src/acpi-tables/src/rsdp.rs | 2 +- src/vmm/src/devices/virtio/vsock/packet.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/acpi-tables/src/fadt.rs b/src/acpi-tables/src/fadt.rs index 5a3a8e5694b..1c937d5cc1b 100644 --- a/src/acpi-tables/src/fadt.rs +++ b/src/acpi-tables/src/fadt.rs @@ -41,7 +41,7 @@ pub const FADT_F_HW_REDUCED_ACPI: u8 = 20; /// the pointer to the DSDT table. /// More information about this table can be found in the ACPI specification: /// https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#fixed-acpi-description-table-fadt -#[repr(packed)] +#[repr(C, packed)] #[derive(Debug, Copy, Clone, Default, IntoBytes, Immutable)] pub struct Fadt { header: SdtHeader, diff --git a/src/acpi-tables/src/lib.rs b/src/acpi-tables/src/lib.rs index 301a2d1cc95..321328047ed 100644 --- a/src/acpi-tables/src/lib.rs +++ b/src/acpi-tables/src/lib.rs @@ -49,7 +49,7 @@ pub enum AcpiError { pub type Result = std::result::Result; /// ACPI type representing memory addresses -#[repr(packed)] +#[repr(C, packed)] #[derive(IntoBytes, Immutable, Clone, Copy, Debug, Default)] pub struct GenericAddressStructure { pub address_space_id: u8, @@ -78,7 +78,7 @@ impl GenericAddressStructure { } /// Header included in all System Descriptor Tables -#[repr(packed)] +#[repr(C, packed)] #[derive(Clone, Debug, Copy, Default, IntoBytes, Immutable)] pub struct SdtHeader { pub signature: [u8; 4], diff --git a/src/acpi-tables/src/madt.rs b/src/acpi-tables/src/madt.rs index 28f5c108b40..c7a11161f5d 100644 --- a/src/acpi-tables/src/madt.rs +++ b/src/acpi-tables/src/madt.rs @@ -17,7 +17,7 @@ const MADT_CPU_ENABLE_FLAG: u32 = 0; // them as bytes in guest memory, so here we just ignore dead code to avoid having to name // everything with an underscore prefix #[allow(dead_code)] -#[repr(packed)] +#[repr(C, packed)] #[derive(Copy, Clone, Debug, Default, IntoBytes, Immutable)] pub struct LocalAPIC { r#type: u8, @@ -43,7 +43,7 @@ impl LocalAPIC { // them as bytes in guest memory, so here we just ignore dead code to avoid having to name // everything with an underscore prefix #[allow(dead_code)] -#[repr(packed)] +#[repr(C, packed)] #[derive(Copy, Clone, Debug, Default, IntoBytes, Immutable)] pub struct IoAPIC { r#type: u8, @@ -71,7 +71,7 @@ impl IoAPIC { // them as bytes in guest memory, so here we just ignore dead code to avoid having to name // everything with an underscore prefix #[allow(dead_code)] -#[repr(packed)] +#[repr(C, packed)] #[derive(Debug, IntoBytes, Immutable)] struct MadtHeader { sdt: SdtHeader, diff --git a/src/acpi-tables/src/rsdp.rs b/src/acpi-tables/src/rsdp.rs index aa413b3cdfb..b2318c6688d 100644 --- a/src/acpi-tables/src/rsdp.rs +++ b/src/acpi-tables/src/rsdp.rs @@ -21,7 +21,7 @@ use crate::{checksum, Result, Sdt}; /// a pointer to XSDT /// More information about this structure can be found in the ACPI specification: /// https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#root-system-description-pointer-rsdp -#[repr(packed)] +#[repr(C, packed)] #[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)] pub struct Rsdp { signature: [u8; 8], diff --git a/src/vmm/src/devices/virtio/vsock/packet.rs b/src/vmm/src/devices/virtio/vsock/packet.rs index fb79c76292f..0927dcf7323 100644 --- a/src/vmm/src/devices/virtio/vsock/packet.rs +++ b/src/vmm/src/devices/virtio/vsock/packet.rs @@ -45,7 +45,7 @@ use crate::vstate::memory::{ByteValued, GuestMemoryMmap}; // The mirroring struct is only used privately by `VsockPacket`, that offers getter and setter // methods, for each struct field, that will also handle the correct endianess. -#[repr(packed)] +#[repr(C, packed)] #[derive(Copy, Clone, Debug, Default)] pub struct VsockPacketHeader { // Source CID. From 5e8379f7ddb93b5065c208e54eb167b71cf823b4 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:16:49 +0000 Subject: [PATCH 342/464] chore(example): fix compilation warning for unused return The compiler complains that we're not consuming the output of `exec`. Let's be explicit about ignoring it. Signed-off-by: Riccardo Mancini --- src/firecracker/examples/seccomp/jailer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firecracker/examples/seccomp/jailer.rs b/src/firecracker/examples/seccomp/jailer.rs index 47f4a667749..62e4b84ea52 100644 --- a/src/firecracker/examples/seccomp/jailer.rs +++ b/src/firecracker/examples/seccomp/jailer.rs @@ -18,7 +18,7 @@ fn main() { // Loads filters. apply_filter(map.get("main").unwrap()).unwrap(); - Command::new(exec_file) + let _ = Command::new(exec_file) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) From c436548f025ef8deb3eff50be4f09f8fca30fb3a Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:19:35 +0000 Subject: [PATCH 343/464] chore(clippy): fix `map_or` can be simplified Clippy complains that `map_or` can be simplified. Replace it with `is_some_and`. Signed-off-by: Riccardo Mancini --- src/clippy-tracing/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clippy-tracing/src/main.rs b/src/clippy-tracing/src/main.rs index f39382f1324..c89fb6a5d37 100644 --- a/src/clippy-tracing/src/main.rs +++ b/src/clippy-tracing/src/main.rs @@ -271,7 +271,7 @@ fn exec() -> Result, ExecError> { // The file must not be a `build.rs` file. let not_build_file = !entry_path.ends_with("build.rs"); // The file must be a `.rs` file. - let is_rs_file = entry_path.extension().map_or(false, |ext| ext == "rs"); + let is_rs_file = entry_path.extension().is_some_and(|ext| ext == "rs"); if no_excluded_strings && not_build_file && is_rs_file { let file = OpenOptions::new() From 0e8ab58f9c267ff76aeef441a4dda7d3e7410f8f Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:37:03 +0000 Subject: [PATCH 344/464] chore(clippy): fix needless call to `as_bytes` The call is redundant as len() on a string returns the number of bytes [1]. [1]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_as_bytes Signed-off-by: Riccardo Mancini --- src/vmm/src/test_utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm/src/test_utils/mod.rs b/src/vmm/src/test_utils/mod.rs index 2ca7f5ce773..79026ba6de3 100644 --- a/src/vmm/src/test_utils/mod.rs +++ b/src/vmm/src/test_utils/mod.rs @@ -117,7 +117,7 @@ pub fn create_tmp_socket() -> (TempDir, String) { std::ptr::copy( tmp_socket_path.as_ptr().cast(), socket_addr.sun_path.as_mut_ptr(), - tmp_socket_path.as_bytes().len(), + tmp_socket_path.len(), ); let bind = libc::bind( From 73864133bdf181907fe828a9702728488516e31a Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 12:38:45 +0000 Subject: [PATCH 345/464] chore(clippy): make pointer cast explicit When applying fixes automatically, clippy doesn't know what to do in this case. It's also objectively obscure. Let's replace it with an explicit cast, specifying the pointer types, and modernize the syntax to use `&raw mut`. Signed-off-by: Riccardo Mancini --- src/firecracker/examples/uffd/uffd_utils.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index dcc05151967..a24fd4feaaf 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -5,6 +5,7 @@ #![allow(dead_code)] use std::collections::{HashMap, HashSet}; +use std::ffi::c_void; use std::fs::File; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; use std::os::unix::net::UnixStream; @@ -227,8 +228,8 @@ impl Runtime { self.stream.as_raw_fd(), libc::SOL_SOCKET, libc::SO_PEERCRED, - &mut creds as *mut _ as *mut _, - &mut creds_size as *mut libc::socklen_t, + (&raw mut creds).cast::(), + &raw mut creds_size, ) }; if ret != 0 { From b3a0d37fc2383142d74a00ebc9aec9676396d7e3 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 18:30:32 +0000 Subject: [PATCH 346/464] chore(devctr): bump to v79 The new version has rust toolchain v1.85.0 Signed-off-by: Riccardo Mancini --- tools/devtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devtool b/tools/devtool index 9011510d7e6..44f10657c06 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:-v78} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v79} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. From 72b01fc4dab40b9d7902b1909a139c4aa5135edf Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 16:22:59 +0000 Subject: [PATCH 347/464] chore(clippy): remove unnecessary "ref" in match Binding modifiers may only be written when the default binding mode is `move`. For more information, see [1]. [1]: https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html Signed-off-by: Riccardo Mancini --- src/firecracker/src/api_server/parsed_request.rs | 2 +- src/jailer/src/cgroup.rs | 4 ++-- src/vmm/src/builder.rs | 2 +- src/vmm/src/devices/virtio/block/virtio/io/mod.rs | 2 +- src/vmm/src/devices/virtio/device.rs | 2 +- src/vmm/src/vstate/vcpu/mod.rs | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs index 41d625e9abe..7313419bc9b 100644 --- a/src/firecracker/src/api_server/parsed_request.rs +++ b/src/firecracker/src/api_server/parsed_request.rs @@ -336,7 +336,7 @@ pub mod tests { } match (&self.action, &other.action) { - (RequestAction::Sync(ref sync_req), RequestAction::Sync(ref other_sync_req)) => { + (RequestAction::Sync(sync_req), RequestAction::Sync(other_sync_req)) => { sync_req == other_sync_req } } diff --git a/src/jailer/src/cgroup.rs b/src/jailer/src/cgroup.rs index e49b1acb317..1661b443a13 100644 --- a/src/jailer/src/cgroup.rs +++ b/src/jailer/src/cgroup.rs @@ -234,8 +234,8 @@ pub enum CgroupConfiguration { impl CgroupConfiguration { pub fn setup(&self) -> Result<(), JailerError> { match self { - Self::V1(ref conf) => setup_cgroup_conf(conf), - Self::V2(ref conf) => setup_cgroup_conf(conf), + Self::V1(conf) => setup_cgroup_conf(conf), + Self::V2(conf) => setup_cgroup_conf(conf), } } } diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 9e583f49cc1..bd956cb2b47 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -961,7 +961,7 @@ fn attach_block_devices<'a, I: Iterator>> + Debug>( let locked = block.lock().expect("Poisoned lock"); if locked.root_device() { match locked.partuuid() { - Some(ref partuuid) => { + Some(partuuid) => { cmdline.insert_str(format!("root=PARTUUID={}", partuuid))? } None => cmdline.insert_str("root=/dev/vda")?, diff --git a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs index cc49dae3eb7..a43ab1e3b4b 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs @@ -223,7 +223,7 @@ pub mod tests { } fn assert_async_execution(mem: &GuestMemoryMmap, engine: &mut FileEngine<()>, count: u32) { - if let FileEngine::Async(ref mut engine) = engine { + if let FileEngine::Async(engine) = engine { engine.drain(false).unwrap(); assert_eq!(engine.pop(mem).unwrap().unwrap().result().unwrap(), count); } diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs index 7e67bb0f189..d6d5d28386b 100644 --- a/src/vmm/src/devices/virtio/device.rs +++ b/src/vmm/src/devices/virtio/device.rs @@ -38,7 +38,7 @@ impl DeviceState { /// Gets the memory attached to the device if it is activated. pub fn mem(&self) -> Option<&GuestMemoryMmap> { match self { - DeviceState::Activated(ref mem) => Some(mem), + DeviceState::Activated(mem) => Some(mem), DeviceState::Inactive => None, } } diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 047b40b133a..8af05809a7d 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -675,8 +675,8 @@ impl fmt::Debug for VcpuResponse { Resumed => write!(f, "VcpuResponse::Resumed"), Exited(code) => write!(f, "VcpuResponse::Exited({:?})", code), SavedState(_) => write!(f, "VcpuResponse::SavedState"), - Error(ref err) => write!(f, "VcpuResponse::Error({:?})", err), - NotAllowed(ref reason) => write!(f, "VcpuResponse::NotAllowed({})", reason), + Error(err) => write!(f, "VcpuResponse::Error({:?})", err), + NotAllowed(reason) => write!(f, "VcpuResponse::NotAllowed({})", reason), DumpedCpuConfig(_) => write!(f, "VcpuResponse::DumpedCpuConfig"), } } @@ -920,7 +920,7 @@ pub(crate) mod tests { (NotAllowed(_), NotAllowed(_)) | (SavedState(_), SavedState(_)) | (DumpedCpuConfig(_), DumpedCpuConfig(_)) => true, - (Error(ref err), Error(ref other_err)) => { + (Error(err), Error(other_err)) => { format!("{:?}", err) == format!("{:?}", other_err) } _ => false, From 6ee0d9128f9d84289a5d6ac3c5d52874f2453faf Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:09:39 +0000 Subject: [PATCH 348/464] chore(clippy): mark env vars set/remove as unsafe In Rust 2024 these are considered unsafe operations, but it's safe to edit them from a single threaded program. Signed-off-by: Riccardo Mancini --- src/jailer/src/main.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs index f5ebd663b02..7c97b618d9e 100644 --- a/src/jailer/src/main.rs +++ b/src/jailer/src/main.rs @@ -288,7 +288,10 @@ fn clean_env_vars() { // the parent process so there are no leaks // inside the jailer environment for (key, _) in p_env::vars() { - p_env::remove_var(key); + // SAFETY: the function is safe to call in a single-threaded program + unsafe { + p_env::remove_var(key); + } } } @@ -423,7 +426,10 @@ mod tests { // Set environment variables for env_var in env_vars.iter() { - env::set_var(env_var, "0"); + // SAFETY: the function is safe to call in a single-threaded program + unsafe { + env::set_var(env_var, "0"); + } } // Cleanup the environment From 74aecaa4cd0a8f5edf8106a39a7fef8cef06ec74 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:12:51 +0000 Subject: [PATCH 349/464] chore(clippy): explicitly mark unsafe calls in unsafe functions In Rust 2024 edition, it is required to mark which parts of an unsafe functions are unsafe. Signed-off-by: Riccardo Mancini --- src/vmm/src/devices/virtio/iov_deque.rs | 3 ++- src/vmm/src/devices/virtio/iovec.rs | 13 ++++++++++--- src/vmm/src/devices/virtio/net/device.rs | 3 ++- src/vmm/src/vstate/vcpu/mod.rs | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs index b28d7076f43..55587d83843 100644 --- a/src/vmm/src/devices/virtio/iov_deque.rs +++ b/src/vmm/src/devices/virtio/iov_deque.rs @@ -120,7 +120,8 @@ impl IovDeque { fd: c_int, offset: off_t, ) -> Result<*mut c_void, IovDequeError> { - let ptr = libc::mmap(addr, len, prot, flags, fd, offset); + // SAFETY: caller should ensure the parameters are valid + let ptr = unsafe { libc::mmap(addr, len, prot, flags, fd, offset) }; if ptr == libc::MAP_FAILED { return Err(IovDequeError::Mmap(std::io::Error::last_os_error())); } diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index c9893260d9e..b4028a217b1 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -100,7 +100,10 @@ impl IoVecBuffer { head: DescriptorChain, ) -> Result { let mut new_buffer = Self::default(); - new_buffer.load_descriptor_chain(mem, head)?; + // SAFETY: descriptor chain cannot be referencing the same memory location as another chain + unsafe { + new_buffer.load_descriptor_chain(mem, head)?; + } Ok(new_buffer) } @@ -328,7 +331,8 @@ impl IoVecBufferMut { head: DescriptorChain, ) -> Result<(), IoVecError> { self.clear(); - let _ = self.append_descriptor_chain(mem, head)?; + // SAFETY: descriptor chain cannot be referencing the same memory location as another chain + let _ = unsafe { self.append_descriptor_chain(mem, head)? }; Ok(()) } @@ -358,7 +362,10 @@ impl IoVecBufferMut { head: DescriptorChain, ) -> Result { let mut new_buffer = Self::new()?; - new_buffer.load_descriptor_chain(mem, head)?; + // SAFETY: descriptor chain cannot be referencing the same memory location as another chain + unsafe { + new_buffer.load_descriptor_chain(mem, head)?; + } Ok(new_buffer) } diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 3e984e4fc76..5b8e21ac21a 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -135,7 +135,8 @@ impl RxBuffers { mem: &GuestMemoryMmap, head: DescriptorChain, ) -> Result<(), AddRxBufferError> { - let parsed_dc = self.iovec.append_descriptor_chain(mem, head)?; + // SAFETY: descriptor chain cannot be referencing the same memory location as another chain + let parsed_dc = unsafe { self.iovec.append_descriptor_chain(mem, head)? }; if parsed_dc.length < self.min_buffer_size { self.iovec.drop_chain_back(&parsed_dc); return Err(AddRxBufferError::BufferTooSmall); diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 8af05809a7d..4fb430a9c39 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -176,9 +176,9 @@ impl Vcpu { { Self::TLS_VCPU_PTR.with(|cell: &VcpuCell| { if let Some(vcpu_ptr) = cell.get() { - // Dereferencing here is safe since `TLS_VCPU_PTR` is populated/non-empty, + // SAFETY: Dereferencing here is safe since `TLS_VCPU_PTR` is populated/non-empty, // and it is being cleared on `Vcpu::drop` so there is no dangling pointer. - let vcpu_ref = &mut *vcpu_ptr; + let vcpu_ref = unsafe { &mut *vcpu_ptr }; func(vcpu_ref); Ok(()) } else { From 5c19583ac15ecad47db95e09febe1f95ded970c3 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:14:30 +0000 Subject: [PATCH 350/464] chore(clippy): mark extern blocks as unsafe In Rust 2024 edition, extern blocks must be marked unsafe. Signed-off-by: Riccardo Mancini --- src/vmm/src/utils/signal.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vmm/src/utils/signal.rs b/src/vmm/src/utils/signal.rs index 172ae1b376e..5178c7ec3c1 100644 --- a/src/vmm/src/utils/signal.rs +++ b/src/vmm/src/utils/signal.rs @@ -4,19 +4,21 @@ use libc::c_int; pub use vmm_sys_util::signal::*; -extern "C" { - fn __libc_current_sigrtmin() -> c_int; - fn __libc_current_sigrtmax() -> c_int; +// SAFETY: these are valid libc functions +unsafe extern "C" { + // SAFETY: Function has no invariants that can be broken. + safe fn __libc_current_sigrtmin() -> c_int; + + // SAFETY: Function has no invariants that can be broken. + safe fn __libc_current_sigrtmax() -> c_int; } /// Sigrtmin pub fn sigrtmin() -> c_int { - // SAFETY: Function has no invariants that can be broken. - unsafe { __libc_current_sigrtmin() } + __libc_current_sigrtmin() } /// Sigrtmax pub fn sigrtmax() -> c_int { - // SAFETY: Function has no invariants that can be broken. - unsafe { __libc_current_sigrtmax() } + __libc_current_sigrtmax() } From 4d8884578b39bd6b1260a55a6212add5a1a67c37 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:15:19 +0000 Subject: [PATCH 351/464] chore(bindgen): use generated as prefix instead of gen In Rust 2024 edition, gen is a keyword reserved for future use. This change updates bindgen to change the destination of the generated files. I've tested this by rerunning bindgen.sh The next change will switch all files to reference the new path. Signed-off-by: Riccardo Mancini --- ...hange-c_char-to-c_uchar-in-ifrn_name.patch | 12 +++--- tools/bindgen.sh | 43 ++++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/tools/bindgen-patches/0001-change-c_char-to-c_uchar-in-ifrn_name.patch b/tools/bindgen-patches/0001-change-c_char-to-c_uchar-in-ifrn_name.patch index 59c5abff2fe..1c05555a384 100644 --- a/tools/bindgen-patches/0001-change-c_char-to-c_uchar-in-ifrn_name.patch +++ b/tools/bindgen-patches/0001-change-c_char-to-c_uchar-in-ifrn_name.patch @@ -1,16 +1,16 @@ -diff --git a/src/vmm/src/devices/virtio/net/gen/iff.rs b/src/vmm/src/devices/virtio/net/gen/iff.rs +diff --git a/src/vmm/src/devices/virtio/net/generated/iff.rs b/src/vmm/src/devices/virtio/net/generated/iff.rs index 04e38396..54111c6b 100644 ---- a/src/vmm/src/devices/virtio/net/gen/iff.rs -+++ b/src/vmm/src/devices/virtio/net/gen/iff.rs -@@ -836,7 +836,7 @@ pub struct ifreq { +--- a/src/vmm/src/devices/virtio/net/generated/iff.rs ++++ b/src/vmm/src/devices/virtio/net/generated/iff.rs +@@ -325,7 +325,7 @@ #[repr(C)] #[derive(Copy, Clone)] pub union ifreq__bindgen_ty_1 { - pub ifrn_name: [::std::os::raw::c_char; 16usize], + pub ifrn_name: [::std::os::raw::c_uchar; 16usize], } - #[test] - fn bindgen_test_layout_ifreq__bindgen_ty_1() { + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { -- 2.40.1 diff --git a/tools/bindgen.sh b/tools/bindgen.sh index 6c64bc5be93..872b3427b67 100755 --- a/tools/bindgen.sh +++ b/tools/bindgen.sh @@ -34,7 +34,8 @@ function fc-bindgen { clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] EOF @@ -44,14 +45,14 @@ EOF KERNEL_HEADERS_HOME="/usr" info "BINDGEN sockios.h" -fc-bindgen "$KERNEL_HEADERS_HOME/include/linux/sockios.h" |replace_linux_int_types >src/vmm/src/devices/virtio/net/gen/sockios.rs +fc-bindgen "$KERNEL_HEADERS_HOME/include/linux/sockios.h" |replace_linux_int_types >src/vmm/src/devices/virtio/net/generated/sockios.rs info "BINDGEN if.h" fc-bindgen "$KERNEL_HEADERS_HOME/include/linux/if.h" \ --allowlist-var='IF.*' \ --allowlist-type='if.*' \ --allowlist-type="net_device.*" \ - -- -D __UAPI_DEF_IF_IFNAMSIZ -D __UAPI_DEF_IF_NET_DEVICE_FLAGS -D __UAPI_DEF_IF_IFREQ -D __UAPI_DEF_IF_IFMAP >src/vmm/src/devices/virtio/net/gen/iff.rs + -- -D __UAPI_DEF_IF_IFNAMSIZ -D __UAPI_DEF_IF_NET_DEVICE_FLAGS -D __UAPI_DEF_IF_IFREQ -D __UAPI_DEF_IF_IFMAP >src/vmm/src/devices/virtio/net/generated/iff.rs info "BINDGEN if_tun.h" fc-bindgen \ @@ -63,37 +64,37 @@ fc-bindgen \ --allowlist-var='IFF_VNET_HDR' \ --allowlist-var='ETH_.*' \ --allowlist-type='ifreq' \ - "$KERNEL_HEADERS_HOME/include/linux/if_tun.h" >src/vmm/src/devices/virtio/net/gen/if_tun.rs + "$KERNEL_HEADERS_HOME/include/linux/if_tun.h" >src/vmm/src/devices/virtio/net/generated/if_tun.rs info "BINDGEN virtio_ring.h" fc-bindgen \ --allowlist-var "VIRTIO_RING_F_EVENT_IDX" \ - "$KERNEL_HEADERS_HOME/include/linux/virtio_ring.h" >src/vmm/src/devices/virtio/gen/virtio_ring.rs + "$KERNEL_HEADERS_HOME/include/linux/virtio_ring.h" >src/vmm/src/devices/virtio/generated/virtio_ring.rs info "BINDGEN virtio_blk.h" fc-bindgen \ --allowlist-var "VIRTIO_BLK_.*" \ --allowlist-var "VIRTIO_F_.*" \ - "$KERNEL_HEADERS_HOME/include/linux/virtio_blk.h" >src/vmm/src/devices/virtio/gen/virtio_blk.rs + "$KERNEL_HEADERS_HOME/include/linux/virtio_blk.h" >src/vmm/src/devices/virtio/generated/virtio_blk.rs info "BINDGEN virtio_net.h" fc-bindgen \ --allowlist-var "VIRTIO_NET_F_.*" \ --allowlist-var "VIRTIO_F_.*" \ --allowlist-type "virtio_net_hdr_v1" \ - "$KERNEL_HEADERS_HOME/include/linux/virtio_net.h" >src/vmm/src/devices/virtio/gen/virtio_net.rs + "$KERNEL_HEADERS_HOME/include/linux/virtio_net.h" >src/vmm/src/devices/virtio/generated/virtio_net.rs info "BINDGEN virtio_rng.h" fc-bindgen \ --allowlist-var "VIRTIO_RNG_.*" \ --allowlist-var "VIRTIO_F_.*" \ - "$KERNEL_HEADERS_HOME/include/linux/virtio_rng.h" >src/vmm/src/devices/virtio/gen/virtio_rng.rs + "$KERNEL_HEADERS_HOME/include/linux/virtio_rng.h" >src/vmm/src/devices/virtio/generated/virtio_rng.rs info "BINDGEN prctl.h" fc-bindgen \ --allowlist-var "PR_.*" \ - "$KERNEL_HEADERS_HOME/include/linux/prctl.h" >src/firecracker/src/gen/prctl.rs -sed -i '/PR_SET_SPECULATION_CTRL/s/u32/i32/g' src/firecracker/src/gen/prctl.rs + "$KERNEL_HEADERS_HOME/include/linux/prctl.h" >src/firecracker/src/generated/prctl.rs +sed -i '/PR_SET_SPECULATION_CTRL/s/u32/i32/g' src/firecracker/src/generated/prctl.rs # https://www.kernel.org/doc/Documentation/kbuild/headers_install.txt # The Linux repo is huge. Just copy what we need. @@ -102,7 +103,7 @@ git clone --branch linux-5.10.y --depth 1 https://github.com/amazonlinux/linux a info "BINDGEN mpspec_def.h" fc-bindgen amazonlinux-v5.10.y/arch/x86/include/asm/mpspec_def.h \ - >src/vmm/src/arch/x86_64/gen/mpspec.rs + >src/vmm/src/arch/x86_64/generated/mpspec.rs # https://github.com/rust-lang/rust-bindgen/issues/1274 info "BINDGEN msr-index.h" @@ -114,8 +115,8 @@ fc-bindgen amazonlinux-v5.10.y/arch/x86/include/asm/msr-index.h \ -Iamazonlinux-v5.10.y/include/ \ -Iamazonlinux-v5.10.y/arch/x86/include/ \ -Wno-macro-redefined \ - >src/vmm/src/arch/x86_64/gen/msr_index.rs -perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/gen/msr_index.rs + >src/vmm/src/arch/x86_64/generated/msr_index.rs +perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/generated/msr_index.rs info "BINDGEN perf_event.h" grep "MSR_ARCH_PERFMON_" amazonlinux-v5.10.y/arch/x86/include/asm/perf_event.h \ @@ -123,8 +124,8 @@ grep "MSR_ARCH_PERFMON_" amazonlinux-v5.10.y/arch/x86/include/asm/perf_event.h \ fc-bindgen amazonlinux-v5.10.y/arch/x86/include/asm/perf_event_msr.h \ --allowlist-var "^MSR_ARCH_PERFMON_.*$" \ -- \ - >src/vmm/src/arch/x86_64/gen/perf_event.rs -perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/gen/perf_event.rs + >src/vmm/src/arch/x86_64/generated/perf_event.rs +perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/generated/perf_event.rs info "BINDGEN hyperv.h" grep "HV_X64_MSR_" amazonlinux-v5.10.y/arch/x86/kvm/hyperv.h \ @@ -132,8 +133,8 @@ grep "HV_X64_MSR_" amazonlinux-v5.10.y/arch/x86/kvm/hyperv.h \ fc-bindgen amazonlinux-v5.10.y/arch/x86/kvm/hyperv_msr.h \ --allowlist-var "^HV_X64_MSR_.*$" \ -- \ - >src/vmm/src/arch/x86_64/gen/hyperv.rs -perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/gen/hyperv.rs + >src/vmm/src/arch/x86_64/generated/hyperv.rs +perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/generated/hyperv.rs info "BINDGEN hyperv-tlfs.h" grep "HV_X64_MSR_" amazonlinux-v5.10.y/arch/x86/include/asm/hyperv-tlfs.h \ @@ -141,8 +142,8 @@ grep "HV_X64_MSR_" amazonlinux-v5.10.y/arch/x86/include/asm/hyperv-tlfs.h \ fc-bindgen amazonlinux-v5.10.y/arch/x86/include/asm/hyperv-tlfs_msr.h \ --allowlist-var "^HV_X64_MSR_.*$" \ -- \ - >src/vmm/src/arch/x86_64/gen/hyperv_tlfs.rs -perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/gen/hyperv_tlfs.rs + >src/vmm/src/arch/x86_64/generated/hyperv_tlfs.rs +perl -i -pe 's/= (\d+);/sprintf("= 0x%x;",$1)/eg' src/vmm/src/arch/x86_64/generated/hyperv_tlfs.rs info "BINDGEN io_uring.h" fc-bindgen \ @@ -152,7 +153,7 @@ fc-bindgen \ --allowlist-type "io_uring_.+" \ --allowlist-type "io_.qring_offsets" \ "amazonlinux-v5.10.y/include/uapi/linux/io_uring.h" \ - >src/vmm/src/io_uring/gen.rs + >src/vmm/src/io_uring/generated.rs # Latest upstream kernel KERNEL_SRC_DIR="linux" @@ -161,7 +162,7 @@ KERNEL_SRC_DIR="linux" info "BINDGEN asm/prctl.h" fc-bindgen \ --allowlist-var "ARCH_.*" \ - "${KERNEL_SRC_DIR}/arch/x86/include/uapi/asm/prctl.h" >src/vmm/src/arch/x86_64/gen/arch_prctl.rs + "${KERNEL_SRC_DIR}/arch/x86/include/uapi/asm/prctl.h" >src/vmm/src/arch/x86_64/generated/arch_prctl.rs # Apply any patches info "Apply patches" From 82de14bbec15f751e1002db9ab8b2e1619fcbd58 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:22:05 +0000 Subject: [PATCH 352/464] chore: regenerate auto-generated files in new generated/ prefix This change switches the generated files location from gen/ to generated/, updating all references in the code. Signed-off-by: Riccardo Mancini --- docs/tracing.md | 2 +- .../src/template/dump/x86_64.rs | 2 +- src/firecracker/src/{gen => generated}/mod.rs | 0 .../src/{gen => generated}/prctl.rs | 31 +- src/firecracker/src/main.rs | 8 +- src/vmm/src/arch/x86_64/gen/mpspec.rs | 825 -------- .../x86_64/{gen => generated}/arch_prctl.rs | 3 +- .../arch/x86_64/{gen => generated}/hyperv.rs | 5 +- .../x86_64/{gen => generated}/hyperv_tlfs.rs | 5 +- .../src/arch/x86_64/{gen => generated}/mod.rs | 0 src/vmm/src/arch/x86_64/generated/mpspec.rs | 267 +++ .../x86_64/{gen => generated}/msr_index.rs | 5 +- .../x86_64/{gen => generated}/perf_event.rs | 5 +- src/vmm/src/arch/x86_64/mod.rs | 2 +- src/vmm/src/arch/x86_64/mptable.rs | 2 +- src/vmm/src/arch/x86_64/msr.rs | 8 +- src/vmm/src/arch/x86_64/xstate.rs | 2 +- src/vmm/src/cpu_config/x86_64/cpuid/common.rs | 2 +- src/vmm/src/devices/virtio/balloon/device.rs | 2 +- .../devices/virtio/block/vhost_user/device.rs | 4 +- .../src/devices/virtio/block/virtio/device.rs | 4 +- .../devices/virtio/block/virtio/persist.rs | 2 +- .../devices/virtio/block/virtio/request.rs | 2 +- src/vmm/src/devices/virtio/gen/virtio_net.rs | 336 ---- .../devices/virtio/{gen => generated}/mod.rs | 0 .../virtio/{gen => generated}/virtio_blk.rs | 38 +- .../devices/virtio/generated/virtio_net.rs | 184 ++ .../virtio/{gen => generated}/virtio_ring.rs | 5 +- .../virtio/{gen => generated}/virtio_rng.rs | 10 +- src/vmm/src/devices/virtio/mod.rs | 2 +- src/vmm/src/devices/virtio/net/device.rs | 26 +- src/vmm/src/devices/virtio/net/gen/iff.rs | 1187 ------------ .../virtio/net/{gen => generated}/if_tun.rs | 118 +- .../src/devices/virtio/net/generated/iff.rs | 465 +++++ .../virtio/net/{gen => generated}/mod.rs | 0 .../virtio/net/{gen => generated}/sockios.rs | 5 +- src/vmm/src/devices/virtio/net/mod.rs | 2 +- src/vmm/src/devices/virtio/net/tap.rs | 16 +- src/vmm/src/devices/virtio/net/test_utils.rs | 12 +- src/vmm/src/devices/virtio/persist.rs | 2 +- src/vmm/src/devices/virtio/rng/device.rs | 2 +- src/vmm/src/io_uring/gen.rs | 1712 ----------------- src/vmm/src/io_uring/generated.rs | 728 +++++++ src/vmm/src/io_uring/mod.rs | 23 +- src/vmm/src/io_uring/operation/cqe.rs | 2 +- src/vmm/src/io_uring/operation/mod.rs | 10 +- src/vmm/src/io_uring/operation/sqe.rs | 2 +- src/vmm/src/io_uring/probe.rs | 2 +- src/vmm/src/io_uring/queue/completion.rs | 12 +- src/vmm/src/io_uring/queue/submission.rs | 16 +- src/vmm/src/io_uring/restriction.rs | 10 +- src/vmm/src/vstate/vcpu/x86_64.rs | 2 +- .../integration_tests/build/test_coverage.py | 2 +- 53 files changed, 1855 insertions(+), 4264 deletions(-) rename src/firecracker/src/{gen => generated}/mod.rs (100%) rename src/firecracker/src/{gen => generated}/prctl.rs (81%) delete mode 100644 src/vmm/src/arch/x86_64/gen/mpspec.rs rename src/vmm/src/arch/x86_64/{gen => generated}/arch_prctl.rs (95%) rename src/vmm/src/arch/x86_64/{gen => generated}/hyperv.rs (83%) rename src/vmm/src/arch/x86_64/{gen => generated}/hyperv_tlfs.rs (96%) rename src/vmm/src/arch/x86_64/{gen => generated}/mod.rs (100%) create mode 100644 src/vmm/src/arch/x86_64/generated/mpspec.rs rename src/vmm/src/arch/x86_64/{gen => generated}/msr_index.rs (99%) rename src/vmm/src/arch/x86_64/{gen => generated}/perf_event.rs (85%) delete mode 100644 src/vmm/src/devices/virtio/gen/virtio_net.rs rename src/vmm/src/devices/virtio/{gen => generated}/mod.rs (100%) rename src/vmm/src/devices/virtio/{gen => generated}/virtio_blk.rs (53%) create mode 100644 src/vmm/src/devices/virtio/generated/virtio_net.rs rename src/vmm/src/devices/virtio/{gen => generated}/virtio_ring.rs (72%) rename src/vmm/src/devices/virtio/{gen => generated}/virtio_rng.rs (65%) delete mode 100644 src/vmm/src/devices/virtio/net/gen/iff.rs rename src/vmm/src/devices/virtio/net/{gen => generated}/if_tun.rs (66%) create mode 100644 src/vmm/src/devices/virtio/net/generated/iff.rs rename src/vmm/src/devices/virtio/net/{gen => generated}/mod.rs (100%) rename src/vmm/src/devices/virtio/net/{gen => generated}/sockios.rs (96%) delete mode 100644 src/vmm/src/io_uring/gen.rs create mode 100644 src/vmm/src/io_uring/generated.rs diff --git a/docs/tracing.md b/docs/tracing.md index ede82b148be..dd9f284c595 100644 --- a/docs/tracing.md +++ b/docs/tracing.md @@ -46,7 +46,7 @@ clippy-tracing \ --action fix \ --path ./src \ --exclude benches \ - --exclude virtio/gen,bindings.rs,net/gen \ + --exclude virtio/generated,bindings.rs,net/generated \ --exclude log-instrument-macros/,log-instrument/,clippy-tracing/ \ --exclude vmm_config/logger.rs,logger/,signal_handler.rs,time.rs ``` diff --git a/src/cpu-template-helper/src/template/dump/x86_64.rs b/src/cpu-template-helper/src/template/dump/x86_64.rs index 75eae9d0a15..8d97080d5e7 100644 --- a/src/cpu-template-helper/src/template/dump/x86_64.rs +++ b/src/cpu-template-helper/src/template/dump/x86_64.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; -use vmm::arch::x86_64::gen::msr_index::*; +use vmm::arch::x86_64::generated::msr_index::*; use vmm::arch::x86_64::msr::MsrRange; use vmm::cpu_config::templates::{CpuConfiguration, CustomCpuTemplate, RegisterValueFilter}; use vmm::cpu_config::x86_64::cpuid::common::get_vendor_id_from_host; diff --git a/src/firecracker/src/gen/mod.rs b/src/firecracker/src/generated/mod.rs similarity index 100% rename from src/firecracker/src/gen/mod.rs rename to src/firecracker/src/generated/mod.rs diff --git a/src/firecracker/src/gen/prctl.rs b/src/firecracker/src/generated/prctl.rs similarity index 81% rename from src/firecracker/src/gen/prctl.rs rename to src/firecracker/src/generated/prctl.rs index e46a41ce5e9..c4c15df92d3 100644 --- a/src/firecracker/src/gen/prctl.rs +++ b/src/firecracker/src/generated/prctl.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const PR_SET_PDEATHSIG: u32 = 1; @@ -152,3 +153,29 @@ pub const PR_SCHED_CORE_CREATE: u32 = 1; pub const PR_SCHED_CORE_SHARE_TO: u32 = 2; pub const PR_SCHED_CORE_SHARE_FROM: u32 = 3; pub const PR_SCHED_CORE_MAX: u32 = 4; +pub const PR_SCHED_CORE_SCOPE_THREAD: u32 = 0; +pub const PR_SCHED_CORE_SCOPE_THREAD_GROUP: u32 = 1; +pub const PR_SCHED_CORE_SCOPE_PROCESS_GROUP: u32 = 2; +pub const PR_SME_SET_VL: u32 = 63; +pub const PR_SME_SET_VL_ONEXEC: u32 = 262144; +pub const PR_SME_GET_VL: u32 = 64; +pub const PR_SME_VL_LEN_MASK: u32 = 65535; +pub const PR_SME_VL_INHERIT: u32 = 131072; +pub const PR_SET_MDWE: u32 = 65; +pub const PR_MDWE_REFUSE_EXEC_GAIN: u32 = 1; +pub const PR_MDWE_NO_INHERIT: u32 = 2; +pub const PR_GET_MDWE: u32 = 66; +pub const PR_SET_VMA: u32 = 1398164801; +pub const PR_SET_VMA_ANON_NAME: u32 = 0; +pub const PR_GET_AUXV: u32 = 1096112214; +pub const PR_SET_MEMORY_MERGE: u32 = 67; +pub const PR_GET_MEMORY_MERGE: u32 = 68; +pub const PR_RISCV_V_SET_CONTROL: u32 = 69; +pub const PR_RISCV_V_GET_CONTROL: u32 = 70; +pub const PR_RISCV_V_VSTATE_CTRL_DEFAULT: u32 = 0; +pub const PR_RISCV_V_VSTATE_CTRL_OFF: u32 = 1; +pub const PR_RISCV_V_VSTATE_CTRL_ON: u32 = 2; +pub const PR_RISCV_V_VSTATE_CTRL_INHERIT: u32 = 16; +pub const PR_RISCV_V_VSTATE_CTRL_CUR_MASK: u32 = 3; +pub const PR_RISCV_V_VSTATE_CTRL_NEXT_MASK: u32 = 12; +pub const PR_RISCV_V_VSTATE_CTRL_MASK: u32 = 31; diff --git a/src/firecracker/src/main.rs b/src/firecracker/src/main.rs index 27a9957d448..1433603a477 100644 --- a/src/firecracker/src/main.rs +++ b/src/firecracker/src/main.rs @@ -3,7 +3,7 @@ mod api_server; mod api_server_adapter; -mod gen; +mod generated; mod metrics; mod seccomp; @@ -501,9 +501,9 @@ pub fn enable_ssbd_mitigation() { // to leave the latter 2 as zero. let ret = unsafe { libc::prctl( - gen::prctl::PR_SET_SPECULATION_CTRL, - gen::prctl::PR_SPEC_STORE_BYPASS, - gen::prctl::PR_SPEC_FORCE_DISABLE, + generated::prctl::PR_SET_SPECULATION_CTRL, + generated::prctl::PR_SPEC_STORE_BYPASS, + generated::prctl::PR_SPEC_FORCE_DISABLE, 0, 0, ) diff --git a/src/vmm/src/arch/x86_64/gen/mpspec.rs b/src/vmm/src/arch/x86_64/gen/mpspec.rs deleted file mode 100644 index 93103e5bee6..00000000000 --- a/src/vmm/src/arch/x86_64/gen/mpspec.rs +++ /dev/null @@ -1,825 +0,0 @@ -// Copyright 2024 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 -)] - -pub const MPC_SIGNATURE: &[u8; 5] = b"PCMP\0"; -pub const MP_PROCESSOR: u32 = 0; -pub const MP_BUS: u32 = 1; -pub const MP_IOAPIC: u32 = 2; -pub const MP_INTSRC: u32 = 3; -pub const MP_LINTSRC: u32 = 4; -pub const MP_TRANSLATION: u32 = 192; -pub const CPU_ENABLED: u32 = 1; -pub const CPU_BOOTPROCESSOR: u32 = 2; -pub const CPU_STEPPING_MASK: u32 = 15; -pub const CPU_MODEL_MASK: u32 = 240; -pub const CPU_FAMILY_MASK: u32 = 3840; -pub const BUSTYPE_EISA: &[u8; 5] = b"EISA\0"; -pub const BUSTYPE_ISA: &[u8; 4] = b"ISA\0"; -pub const BUSTYPE_INTERN: &[u8; 7] = b"INTERN\0"; -pub const BUSTYPE_MCA: &[u8; 4] = b"MCA\0"; -pub const BUSTYPE_VL: &[u8; 3] = b"VL\0"; -pub const BUSTYPE_PCI: &[u8; 4] = b"PCI\0"; -pub const BUSTYPE_PCMCIA: &[u8; 7] = b"PCMCIA\0"; -pub const BUSTYPE_CBUS: &[u8; 5] = b"CBUS\0"; -pub const BUSTYPE_CBUSII: &[u8; 7] = b"CBUSII\0"; -pub const BUSTYPE_FUTURE: &[u8; 7] = b"FUTURE\0"; -pub const BUSTYPE_MBI: &[u8; 4] = b"MBI\0"; -pub const BUSTYPE_MBII: &[u8; 5] = b"MBII\0"; -pub const BUSTYPE_MPI: &[u8; 4] = b"MPI\0"; -pub const BUSTYPE_MPSA: &[u8; 5] = b"MPSA\0"; -pub const BUSTYPE_NUBUS: &[u8; 6] = b"NUBUS\0"; -pub const BUSTYPE_TC: &[u8; 3] = b"TC\0"; -pub const BUSTYPE_VME: &[u8; 4] = b"VME\0"; -pub const BUSTYPE_XPRESS: &[u8; 7] = b"XPRESS\0"; -pub const MPC_APIC_USABLE: u32 = 1; -pub const MP_IRQPOL_DEFAULT: u32 = 0; -pub const MP_IRQPOL_ACTIVE_HIGH: u32 = 1; -pub const MP_IRQPOL_RESERVED: u32 = 2; -pub const MP_IRQPOL_ACTIVE_LOW: u32 = 3; -pub const MP_IRQPOL_MASK: u32 = 3; -pub const MP_IRQTRIG_DEFAULT: u32 = 0; -pub const MP_IRQTRIG_EDGE: u32 = 4; -pub const MP_IRQTRIG_RESERVED: u32 = 8; -pub const MP_IRQTRIG_LEVEL: u32 = 12; -pub const MP_IRQTRIG_MASK: u32 = 12; -pub const MP_APIC_ALL: u32 = 255; -pub const MPC_OEM_SIGNATURE: &[u8; 5] = b"_OEM\0"; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpf_intel { - pub signature: [::std::os::raw::c_char; 4usize], - pub physptr: ::std::os::raw::c_uint, - pub length: ::std::os::raw::c_uchar, - pub specification: ::std::os::raw::c_uchar, - pub checksum: ::std::os::raw::c_uchar, - pub feature1: ::std::os::raw::c_uchar, - pub feature2: ::std::os::raw::c_uchar, - pub feature3: ::std::os::raw::c_uchar, - pub feature4: ::std::os::raw::c_uchar, - pub feature5: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_mpf_intel() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(mpf_intel)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(mpf_intel)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).signature) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(signature) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).physptr) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(physptr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(length) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).specification) as usize - ptr as usize }, - 9usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(specification) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).checksum) as usize - ptr as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(checksum) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).feature1) as usize - ptr as usize }, - 11usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(feature1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).feature2) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(feature2) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).feature3) as usize - ptr as usize }, - 13usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(feature3) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).feature4) as usize - ptr as usize }, - 14usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(feature4) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).feature5) as usize - ptr as usize }, - 15usize, - concat!( - "Offset of field: ", - stringify!(mpf_intel), - "::", - stringify!(feature5) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_table { - pub signature: [::std::os::raw::c_char; 4usize], - pub length: ::std::os::raw::c_ushort, - pub spec: ::std::os::raw::c_char, - pub checksum: ::std::os::raw::c_char, - pub oem: [::std::os::raw::c_char; 8usize], - pub productid: [::std::os::raw::c_char; 12usize], - pub oemptr: ::std::os::raw::c_uint, - pub oemsize: ::std::os::raw::c_ushort, - pub oemcount: ::std::os::raw::c_ushort, - pub lapic: ::std::os::raw::c_uint, - pub reserved: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_mpc_table() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 44usize, - concat!("Size of: ", stringify!(mpc_table)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(mpc_table)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).signature) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(signature) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(length) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).spec) as usize - ptr as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(spec) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).checksum) as usize - ptr as usize }, - 7usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(checksum) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).oem) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(oem) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).productid) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(productid) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).oemptr) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(oemptr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).oemsize) as usize - ptr as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(oemsize) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).oemcount) as usize - ptr as usize }, - 34usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(oemcount) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).lapic) as usize - ptr as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(lapic) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(mpc_table), - "::", - stringify!(reserved) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_cpu { - pub type_: ::std::os::raw::c_uchar, - pub apicid: ::std::os::raw::c_uchar, - pub apicver: ::std::os::raw::c_uchar, - pub cpuflag: ::std::os::raw::c_uchar, - pub cpufeature: ::std::os::raw::c_uint, - pub featureflag: ::std::os::raw::c_uint, - pub reserved: [::std::os::raw::c_uint; 2usize], -} -#[test] -fn bindgen_test_layout_mpc_cpu() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(mpc_cpu)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(mpc_cpu)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).apicid) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(apicid) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).apicver) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(apicver) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cpuflag) as usize - ptr as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(cpuflag) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cpufeature) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(cpufeature) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).featureflag) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(featureflag) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(mpc_cpu), - "::", - stringify!(reserved) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_bus { - pub type_: ::std::os::raw::c_uchar, - pub busid: ::std::os::raw::c_uchar, - pub bustype: [::std::os::raw::c_uchar; 6usize], -} -#[test] -fn bindgen_test_layout_mpc_bus() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(mpc_bus)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(mpc_bus)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_bus), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).busid) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(mpc_bus), - "::", - stringify!(busid) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).bustype) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(mpc_bus), - "::", - stringify!(bustype) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_ioapic { - pub type_: ::std::os::raw::c_uchar, - pub apicid: ::std::os::raw::c_uchar, - pub apicver: ::std::os::raw::c_uchar, - pub flags: ::std::os::raw::c_uchar, - pub apicaddr: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_mpc_ioapic() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(mpc_ioapic)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(mpc_ioapic)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_ioapic), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).apicid) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(mpc_ioapic), - "::", - stringify!(apicid) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).apicver) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(mpc_ioapic), - "::", - stringify!(apicver) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(mpc_ioapic), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).apicaddr) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_ioapic), - "::", - stringify!(apicaddr) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_intsrc { - pub type_: ::std::os::raw::c_uchar, - pub irqtype: ::std::os::raw::c_uchar, - pub irqflag: ::std::os::raw::c_ushort, - pub srcbus: ::std::os::raw::c_uchar, - pub srcbusirq: ::std::os::raw::c_uchar, - pub dstapic: ::std::os::raw::c_uchar, - pub dstirq: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_mpc_intsrc() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(mpc_intsrc)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(mpc_intsrc)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).irqtype) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(irqtype) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).irqflag) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(irqflag) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).srcbus) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(srcbus) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).srcbusirq) as usize - ptr as usize }, - 5usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(srcbusirq) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dstapic) as usize - ptr as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(dstapic) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dstirq) as usize - ptr as usize }, - 7usize, - concat!( - "Offset of field: ", - stringify!(mpc_intsrc), - "::", - stringify!(dstirq) - ) - ); -} -pub const mp_irq_source_types_mp_INT: mp_irq_source_types = 0; -pub const mp_irq_source_types_mp_NMI: mp_irq_source_types = 1; -pub const mp_irq_source_types_mp_SMI: mp_irq_source_types = 2; -pub const mp_irq_source_types_mp_ExtINT: mp_irq_source_types = 3; -pub type mp_irq_source_types = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_lintsrc { - pub type_: ::std::os::raw::c_uchar, - pub irqtype: ::std::os::raw::c_uchar, - pub irqflag: ::std::os::raw::c_ushort, - pub srcbusid: ::std::os::raw::c_uchar, - pub srcbusirq: ::std::os::raw::c_uchar, - pub destapic: ::std::os::raw::c_uchar, - pub destapiclint: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_mpc_lintsrc() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(mpc_lintsrc)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(mpc_lintsrc)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).irqtype) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(irqtype) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).irqflag) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(irqflag) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).srcbusid) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(srcbusid) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).srcbusirq) as usize - ptr as usize }, - 5usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(srcbusirq) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).destapic) as usize - ptr as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(destapic) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).destapiclint) as usize - ptr as usize }, - 7usize, - concat!( - "Offset of field: ", - stringify!(mpc_lintsrc), - "::", - stringify!(destapiclint) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct mpc_oemtable { - pub signature: [::std::os::raw::c_char; 4usize], - pub length: ::std::os::raw::c_ushort, - pub rev: ::std::os::raw::c_char, - pub checksum: ::std::os::raw::c_char, - pub mpc: [::std::os::raw::c_char; 8usize], -} -#[test] -fn bindgen_test_layout_mpc_oemtable() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(mpc_oemtable)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(mpc_oemtable)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).signature) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(mpc_oemtable), - "::", - stringify!(signature) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(mpc_oemtable), - "::", - stringify!(length) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rev) as usize - ptr as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(mpc_oemtable), - "::", - stringify!(rev) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).checksum) as usize - ptr as usize }, - 7usize, - concat!( - "Offset of field: ", - stringify!(mpc_oemtable), - "::", - stringify!(checksum) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mpc) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(mpc_oemtable), - "::", - stringify!(mpc) - ) - ); -} -pub const mp_bustype_MP_BUS_ISA: mp_bustype = 1; -pub const mp_bustype_MP_BUS_EISA: mp_bustype = 2; -pub const mp_bustype_MP_BUS_PCI: mp_bustype = 3; -pub type mp_bustype = ::std::os::raw::c_uint; diff --git a/src/vmm/src/arch/x86_64/gen/arch_prctl.rs b/src/vmm/src/arch/x86_64/generated/arch_prctl.rs similarity index 95% rename from src/vmm/src/arch/x86_64/gen/arch_prctl.rs rename to src/vmm/src/arch/x86_64/generated/arch_prctl.rs index 768964e494b..44f68883141 100644 --- a/src/vmm/src/arch/x86_64/gen/arch_prctl.rs +++ b/src/vmm/src/arch/x86_64/generated/arch_prctl.rs @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const ARCH_SET_GS: u32 = 4097; diff --git a/src/vmm/src/arch/x86_64/gen/hyperv.rs b/src/vmm/src/arch/x86_64/generated/hyperv.rs similarity index 83% rename from src/vmm/src/arch/x86_64/gen/hyperv.rs rename to src/vmm/src/arch/x86_64/generated/hyperv.rs index 02ccc3adbcc..49dabeaca92 100644 --- a/src/vmm/src/arch/x86_64/gen/hyperv.rs +++ b/src/vmm/src/arch/x86_64/generated/hyperv.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const HV_X64_MSR_SYNDBG_CONTROL: u32 = 0x400000f1; diff --git a/src/vmm/src/arch/x86_64/gen/hyperv_tlfs.rs b/src/vmm/src/arch/x86_64/generated/hyperv_tlfs.rs similarity index 96% rename from src/vmm/src/arch/x86_64/gen/hyperv_tlfs.rs rename to src/vmm/src/arch/x86_64/generated/hyperv_tlfs.rs index 84b770a5506..fae4d497142 100644 --- a/src/vmm/src/arch/x86_64/gen/hyperv_tlfs.rs +++ b/src/vmm/src/arch/x86_64/generated/hyperv_tlfs.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const HV_X64_MSR_GUEST_OS_ID: u32 = 0x40000000; diff --git a/src/vmm/src/arch/x86_64/gen/mod.rs b/src/vmm/src/arch/x86_64/generated/mod.rs similarity index 100% rename from src/vmm/src/arch/x86_64/gen/mod.rs rename to src/vmm/src/arch/x86_64/generated/mod.rs diff --git a/src/vmm/src/arch/x86_64/generated/mpspec.rs b/src/vmm/src/arch/x86_64/generated/mpspec.rs new file mode 100644 index 00000000000..38252548367 --- /dev/null +++ b/src/vmm/src/arch/x86_64/generated/mpspec.rs @@ -0,0 +1,267 @@ +// 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 +)] + +pub const MPC_SIGNATURE: &[u8; 5] = b"PCMP\0"; +pub const MP_PROCESSOR: u32 = 0; +pub const MP_BUS: u32 = 1; +pub const MP_IOAPIC: u32 = 2; +pub const MP_INTSRC: u32 = 3; +pub const MP_LINTSRC: u32 = 4; +pub const MP_TRANSLATION: u32 = 192; +pub const CPU_ENABLED: u32 = 1; +pub const CPU_BOOTPROCESSOR: u32 = 2; +pub const CPU_STEPPING_MASK: u32 = 15; +pub const CPU_MODEL_MASK: u32 = 240; +pub const CPU_FAMILY_MASK: u32 = 3840; +pub const BUSTYPE_EISA: &[u8; 5] = b"EISA\0"; +pub const BUSTYPE_ISA: &[u8; 4] = b"ISA\0"; +pub const BUSTYPE_INTERN: &[u8; 7] = b"INTERN\0"; +pub const BUSTYPE_MCA: &[u8; 4] = b"MCA\0"; +pub const BUSTYPE_VL: &[u8; 3] = b"VL\0"; +pub const BUSTYPE_PCI: &[u8; 4] = b"PCI\0"; +pub const BUSTYPE_PCMCIA: &[u8; 7] = b"PCMCIA\0"; +pub const BUSTYPE_CBUS: &[u8; 5] = b"CBUS\0"; +pub const BUSTYPE_CBUSII: &[u8; 7] = b"CBUSII\0"; +pub const BUSTYPE_FUTURE: &[u8; 7] = b"FUTURE\0"; +pub const BUSTYPE_MBI: &[u8; 4] = b"MBI\0"; +pub const BUSTYPE_MBII: &[u8; 5] = b"MBII\0"; +pub const BUSTYPE_MPI: &[u8; 4] = b"MPI\0"; +pub const BUSTYPE_MPSA: &[u8; 5] = b"MPSA\0"; +pub const BUSTYPE_NUBUS: &[u8; 6] = b"NUBUS\0"; +pub const BUSTYPE_TC: &[u8; 3] = b"TC\0"; +pub const BUSTYPE_VME: &[u8; 4] = b"VME\0"; +pub const BUSTYPE_XPRESS: &[u8; 7] = b"XPRESS\0"; +pub const MPC_APIC_USABLE: u32 = 1; +pub const MP_IRQPOL_DEFAULT: u32 = 0; +pub const MP_IRQPOL_ACTIVE_HIGH: u32 = 1; +pub const MP_IRQPOL_RESERVED: u32 = 2; +pub const MP_IRQPOL_ACTIVE_LOW: u32 = 3; +pub const MP_IRQPOL_MASK: u32 = 3; +pub const MP_IRQTRIG_DEFAULT: u32 = 0; +pub const MP_IRQTRIG_EDGE: u32 = 4; +pub const MP_IRQTRIG_RESERVED: u32 = 8; +pub const MP_IRQTRIG_LEVEL: u32 = 12; +pub const MP_IRQTRIG_MASK: u32 = 12; +pub const MP_APIC_ALL: u32 = 255; +pub const MPC_OEM_SIGNATURE: &[u8; 5] = b"_OEM\0"; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpf_intel { + pub signature: [::std::os::raw::c_char; 4usize], + pub physptr: ::std::os::raw::c_uint, + pub length: ::std::os::raw::c_uchar, + pub specification: ::std::os::raw::c_uchar, + pub checksum: ::std::os::raw::c_uchar, + pub feature1: ::std::os::raw::c_uchar, + pub feature2: ::std::os::raw::c_uchar, + pub feature3: ::std::os::raw::c_uchar, + pub feature4: ::std::os::raw::c_uchar, + pub feature5: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpf_intel"][::std::mem::size_of::() - 16usize]; + ["Alignment of mpf_intel"][::std::mem::align_of::() - 4usize]; + ["Offset of field: mpf_intel::signature"] + [::std::mem::offset_of!(mpf_intel, signature) - 0usize]; + ["Offset of field: mpf_intel::physptr"][::std::mem::offset_of!(mpf_intel, physptr) - 4usize]; + ["Offset of field: mpf_intel::length"][::std::mem::offset_of!(mpf_intel, length) - 8usize]; + ["Offset of field: mpf_intel::specification"] + [::std::mem::offset_of!(mpf_intel, specification) - 9usize]; + ["Offset of field: mpf_intel::checksum"][::std::mem::offset_of!(mpf_intel, checksum) - 10usize]; + ["Offset of field: mpf_intel::feature1"][::std::mem::offset_of!(mpf_intel, feature1) - 11usize]; + ["Offset of field: mpf_intel::feature2"][::std::mem::offset_of!(mpf_intel, feature2) - 12usize]; + ["Offset of field: mpf_intel::feature3"][::std::mem::offset_of!(mpf_intel, feature3) - 13usize]; + ["Offset of field: mpf_intel::feature4"][::std::mem::offset_of!(mpf_intel, feature4) - 14usize]; + ["Offset of field: mpf_intel::feature5"][::std::mem::offset_of!(mpf_intel, feature5) - 15usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_table { + pub signature: [::std::os::raw::c_char; 4usize], + pub length: ::std::os::raw::c_ushort, + pub spec: ::std::os::raw::c_char, + pub checksum: ::std::os::raw::c_char, + pub oem: [::std::os::raw::c_char; 8usize], + pub productid: [::std::os::raw::c_char; 12usize], + pub oemptr: ::std::os::raw::c_uint, + pub oemsize: ::std::os::raw::c_ushort, + pub oemcount: ::std::os::raw::c_ushort, + pub lapic: ::std::os::raw::c_uint, + pub reserved: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_table"][::std::mem::size_of::() - 44usize]; + ["Alignment of mpc_table"][::std::mem::align_of::() - 4usize]; + ["Offset of field: mpc_table::signature"] + [::std::mem::offset_of!(mpc_table, signature) - 0usize]; + ["Offset of field: mpc_table::length"][::std::mem::offset_of!(mpc_table, length) - 4usize]; + ["Offset of field: mpc_table::spec"][::std::mem::offset_of!(mpc_table, spec) - 6usize]; + ["Offset of field: mpc_table::checksum"][::std::mem::offset_of!(mpc_table, checksum) - 7usize]; + ["Offset of field: mpc_table::oem"][::std::mem::offset_of!(mpc_table, oem) - 8usize]; + ["Offset of field: mpc_table::productid"] + [::std::mem::offset_of!(mpc_table, productid) - 16usize]; + ["Offset of field: mpc_table::oemptr"][::std::mem::offset_of!(mpc_table, oemptr) - 28usize]; + ["Offset of field: mpc_table::oemsize"][::std::mem::offset_of!(mpc_table, oemsize) - 32usize]; + ["Offset of field: mpc_table::oemcount"][::std::mem::offset_of!(mpc_table, oemcount) - 34usize]; + ["Offset of field: mpc_table::lapic"][::std::mem::offset_of!(mpc_table, lapic) - 36usize]; + ["Offset of field: mpc_table::reserved"][::std::mem::offset_of!(mpc_table, reserved) - 40usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_cpu { + pub type_: ::std::os::raw::c_uchar, + pub apicid: ::std::os::raw::c_uchar, + pub apicver: ::std::os::raw::c_uchar, + pub cpuflag: ::std::os::raw::c_uchar, + pub cpufeature: ::std::os::raw::c_uint, + pub featureflag: ::std::os::raw::c_uint, + pub reserved: [::std::os::raw::c_uint; 2usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_cpu"][::std::mem::size_of::() - 20usize]; + ["Alignment of mpc_cpu"][::std::mem::align_of::() - 4usize]; + ["Offset of field: mpc_cpu::type_"][::std::mem::offset_of!(mpc_cpu, type_) - 0usize]; + ["Offset of field: mpc_cpu::apicid"][::std::mem::offset_of!(mpc_cpu, apicid) - 1usize]; + ["Offset of field: mpc_cpu::apicver"][::std::mem::offset_of!(mpc_cpu, apicver) - 2usize]; + ["Offset of field: mpc_cpu::cpuflag"][::std::mem::offset_of!(mpc_cpu, cpuflag) - 3usize]; + ["Offset of field: mpc_cpu::cpufeature"][::std::mem::offset_of!(mpc_cpu, cpufeature) - 4usize]; + ["Offset of field: mpc_cpu::featureflag"] + [::std::mem::offset_of!(mpc_cpu, featureflag) - 8usize]; + ["Offset of field: mpc_cpu::reserved"][::std::mem::offset_of!(mpc_cpu, reserved) - 12usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_bus { + pub type_: ::std::os::raw::c_uchar, + pub busid: ::std::os::raw::c_uchar, + pub bustype: [::std::os::raw::c_uchar; 6usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_bus"][::std::mem::size_of::() - 8usize]; + ["Alignment of mpc_bus"][::std::mem::align_of::() - 1usize]; + ["Offset of field: mpc_bus::type_"][::std::mem::offset_of!(mpc_bus, type_) - 0usize]; + ["Offset of field: mpc_bus::busid"][::std::mem::offset_of!(mpc_bus, busid) - 1usize]; + ["Offset of field: mpc_bus::bustype"][::std::mem::offset_of!(mpc_bus, bustype) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_ioapic { + pub type_: ::std::os::raw::c_uchar, + pub apicid: ::std::os::raw::c_uchar, + pub apicver: ::std::os::raw::c_uchar, + pub flags: ::std::os::raw::c_uchar, + pub apicaddr: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_ioapic"][::std::mem::size_of::() - 8usize]; + ["Alignment of mpc_ioapic"][::std::mem::align_of::() - 4usize]; + ["Offset of field: mpc_ioapic::type_"][::std::mem::offset_of!(mpc_ioapic, type_) - 0usize]; + ["Offset of field: mpc_ioapic::apicid"][::std::mem::offset_of!(mpc_ioapic, apicid) - 1usize]; + ["Offset of field: mpc_ioapic::apicver"][::std::mem::offset_of!(mpc_ioapic, apicver) - 2usize]; + ["Offset of field: mpc_ioapic::flags"][::std::mem::offset_of!(mpc_ioapic, flags) - 3usize]; + ["Offset of field: mpc_ioapic::apicaddr"] + [::std::mem::offset_of!(mpc_ioapic, apicaddr) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_intsrc { + pub type_: ::std::os::raw::c_uchar, + pub irqtype: ::std::os::raw::c_uchar, + pub irqflag: ::std::os::raw::c_ushort, + pub srcbus: ::std::os::raw::c_uchar, + pub srcbusirq: ::std::os::raw::c_uchar, + pub dstapic: ::std::os::raw::c_uchar, + pub dstirq: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_intsrc"][::std::mem::size_of::() - 8usize]; + ["Alignment of mpc_intsrc"][::std::mem::align_of::() - 2usize]; + ["Offset of field: mpc_intsrc::type_"][::std::mem::offset_of!(mpc_intsrc, type_) - 0usize]; + ["Offset of field: mpc_intsrc::irqtype"][::std::mem::offset_of!(mpc_intsrc, irqtype) - 1usize]; + ["Offset of field: mpc_intsrc::irqflag"][::std::mem::offset_of!(mpc_intsrc, irqflag) - 2usize]; + ["Offset of field: mpc_intsrc::srcbus"][::std::mem::offset_of!(mpc_intsrc, srcbus) - 4usize]; + ["Offset of field: mpc_intsrc::srcbusirq"] + [::std::mem::offset_of!(mpc_intsrc, srcbusirq) - 5usize]; + ["Offset of field: mpc_intsrc::dstapic"][::std::mem::offset_of!(mpc_intsrc, dstapic) - 6usize]; + ["Offset of field: mpc_intsrc::dstirq"][::std::mem::offset_of!(mpc_intsrc, dstirq) - 7usize]; +}; +pub const mp_irq_source_types_mp_INT: mp_irq_source_types = 0; +pub const mp_irq_source_types_mp_NMI: mp_irq_source_types = 1; +pub const mp_irq_source_types_mp_SMI: mp_irq_source_types = 2; +pub const mp_irq_source_types_mp_ExtINT: mp_irq_source_types = 3; +pub type mp_irq_source_types = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_lintsrc { + pub type_: ::std::os::raw::c_uchar, + pub irqtype: ::std::os::raw::c_uchar, + pub irqflag: ::std::os::raw::c_ushort, + pub srcbusid: ::std::os::raw::c_uchar, + pub srcbusirq: ::std::os::raw::c_uchar, + pub destapic: ::std::os::raw::c_uchar, + pub destapiclint: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_lintsrc"][::std::mem::size_of::() - 8usize]; + ["Alignment of mpc_lintsrc"][::std::mem::align_of::() - 2usize]; + ["Offset of field: mpc_lintsrc::type_"][::std::mem::offset_of!(mpc_lintsrc, type_) - 0usize]; + ["Offset of field: mpc_lintsrc::irqtype"] + [::std::mem::offset_of!(mpc_lintsrc, irqtype) - 1usize]; + ["Offset of field: mpc_lintsrc::irqflag"] + [::std::mem::offset_of!(mpc_lintsrc, irqflag) - 2usize]; + ["Offset of field: mpc_lintsrc::srcbusid"] + [::std::mem::offset_of!(mpc_lintsrc, srcbusid) - 4usize]; + ["Offset of field: mpc_lintsrc::srcbusirq"] + [::std::mem::offset_of!(mpc_lintsrc, srcbusirq) - 5usize]; + ["Offset of field: mpc_lintsrc::destapic"] + [::std::mem::offset_of!(mpc_lintsrc, destapic) - 6usize]; + ["Offset of field: mpc_lintsrc::destapiclint"] + [::std::mem::offset_of!(mpc_lintsrc, destapiclint) - 7usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct mpc_oemtable { + pub signature: [::std::os::raw::c_char; 4usize], + pub length: ::std::os::raw::c_ushort, + pub rev: ::std::os::raw::c_char, + pub checksum: ::std::os::raw::c_char, + pub mpc: [::std::os::raw::c_char; 8usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of mpc_oemtable"][::std::mem::size_of::() - 16usize]; + ["Alignment of mpc_oemtable"][::std::mem::align_of::() - 2usize]; + ["Offset of field: mpc_oemtable::signature"] + [::std::mem::offset_of!(mpc_oemtable, signature) - 0usize]; + ["Offset of field: mpc_oemtable::length"] + [::std::mem::offset_of!(mpc_oemtable, length) - 4usize]; + ["Offset of field: mpc_oemtable::rev"][::std::mem::offset_of!(mpc_oemtable, rev) - 6usize]; + ["Offset of field: mpc_oemtable::checksum"] + [::std::mem::offset_of!(mpc_oemtable, checksum) - 7usize]; + ["Offset of field: mpc_oemtable::mpc"][::std::mem::offset_of!(mpc_oemtable, mpc) - 8usize]; +}; +pub const mp_bustype_MP_BUS_ISA: mp_bustype = 1; +pub const mp_bustype_MP_BUS_EISA: mp_bustype = 2; +pub const mp_bustype_MP_BUS_PCI: mp_bustype = 3; +pub type mp_bustype = ::std::os::raw::c_uint; diff --git a/src/vmm/src/arch/x86_64/gen/msr_index.rs b/src/vmm/src/arch/x86_64/generated/msr_index.rs similarity index 99% rename from src/vmm/src/arch/x86_64/gen/msr_index.rs rename to src/vmm/src/arch/x86_64/generated/msr_index.rs index 0acc88b6fd1..041bffe7ec3 100644 --- a/src/vmm/src/arch/x86_64/gen/msr_index.rs +++ b/src/vmm/src/arch/x86_64/generated/msr_index.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const MSR_EFER: u32 = 0xc0000080; diff --git a/src/vmm/src/arch/x86_64/gen/perf_event.rs b/src/vmm/src/arch/x86_64/generated/perf_event.rs similarity index 85% rename from src/vmm/src/arch/x86_64/gen/perf_event.rs rename to src/vmm/src/arch/x86_64/generated/perf_event.rs index f00951e0c19..66b851e3451 100644 --- a/src/vmm/src/arch/x86_64/gen/perf_event.rs +++ b/src/vmm/src/arch/x86_64/generated/perf_event.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const MSR_ARCH_PERFMON_PERFCTR0: u32 = 0xc1; diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 973e7235c98..a0f6d98889d 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -23,7 +23,7 @@ pub mod regs; pub mod xstate; #[allow(missing_docs)] -pub mod gen; +pub mod generated; use linux_loader::configurator::linux::LinuxBootConfigurator; use linux_loader::configurator::pvh::PvhBootConfigurator; diff --git a/src/vmm/src/arch/x86_64/mptable.rs b/src/vmm/src/arch/x86_64/mptable.rs index 9944ecee8fb..ce93555ad7e 100644 --- a/src/vmm/src/arch/x86_64/mptable.rs +++ b/src/vmm/src/arch/x86_64/mptable.rs @@ -13,7 +13,7 @@ use libc::c_char; use log::debug; use vm_allocator::AllocPolicy; -use crate::arch::x86_64::gen::mpspec; +use crate::arch::x86_64::generated::mpspec; use crate::arch::IRQ_MAX; use crate::device_manager::resources::ResourceAllocator; use crate::vstate::memory::{ diff --git a/src/vmm/src/arch/x86_64/msr.rs b/src/vmm/src/arch/x86_64/msr.rs index 325d6ed6b29..2142eba5aa5 100644 --- a/src/vmm/src/arch/x86_64/msr.rs +++ b/src/vmm/src/arch/x86_64/msr.rs @@ -6,10 +6,10 @@ use bitflags::bitflags; use kvm_bindings::{kvm_msr_entry, MsrList, Msrs}; use kvm_ioctls::{Kvm, VcpuFd}; -use crate::arch::x86_64::gen::hyperv::*; -use crate::arch::x86_64::gen::hyperv_tlfs::*; -use crate::arch::x86_64::gen::msr_index::*; -use crate::arch::x86_64::gen::perf_event::*; +use crate::arch::x86_64::generated::hyperv::*; +use crate::arch::x86_64::generated::hyperv_tlfs::*; +use crate::arch::x86_64::generated::msr_index::*; +use crate::arch::x86_64::generated::perf_event::*; use crate::cpu_config::x86_64::cpuid::common::GetCpuidError; #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] diff --git a/src/vmm/src/arch/x86_64/xstate.rs b/src/vmm/src/arch/x86_64/xstate.rs index 91197d076ba..78e509dc819 100644 --- a/src/vmm/src/arch/x86_64/xstate.rs +++ b/src/vmm/src/arch/x86_64/xstate.rs @@ -3,7 +3,7 @@ use vmm_sys_util::syscall::SyscallReturnCode; -use crate::arch::x86_64::gen::arch_prctl; +use crate::arch::x86_64::generated::arch_prctl; const INTEL_AMX_MASK: u64 = 1u64 << arch_prctl::ARCH_XCOMP_TILEDATA; diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/common.rs b/src/vmm/src/cpu_config/x86_64/cpuid/common.rs index 3b89183293c..4046346e125 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/common.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/common.rs @@ -98,7 +98,7 @@ pub(crate) fn msrs_to_save_by_cpuid(cpuid: &kvm_bindings::CpuId) -> Vec { 0, ebx, MPX_BITINDEX, - [crate::arch::x86_64::gen::msr_index::MSR_IA32_BNDCFGS] + [crate::arch::x86_64::generated::msr_index::MSR_IA32_BNDCFGS] ); // IA32_MTRR_PHYSBASEn, IA32_MTRR_PHYSMASKn diff --git a/src/vmm/src/devices/virtio/balloon/device.rs b/src/vmm/src/devices/virtio/balloon/device.rs index f6be2536de5..9ad34d280b5 100644 --- a/src/vmm/src/devices/virtio/balloon/device.rs +++ b/src/vmm/src/devices/virtio/balloon/device.rs @@ -25,7 +25,7 @@ use super::{ }; use crate::devices::virtio::balloon::BalloonError; use crate::devices::virtio::device::{IrqTrigger, IrqType}; -use crate::devices::virtio::gen::virtio_blk::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_blk::VIRTIO_F_VERSION_1; use crate::logger::IncMetric; use crate::utils::u64_to_usize; use crate::vstate::memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap}; diff --git a/src/vmm/src/devices/virtio/block/vhost_user/device.rs b/src/vmm/src/devices/virtio/block/vhost_user/device.rs index cdd17e2ea98..b8c7a6677df 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/device.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/device.rs @@ -15,10 +15,10 @@ use vmm_sys_util::eventfd::EventFd; use super::{VhostUserBlockError, NUM_QUEUES, QUEUE_SIZE}; use crate::devices::virtio::block::CacheType; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::gen::virtio_blk::{ +use crate::devices::virtio::generated::virtio_blk::{ VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_F_VERSION_1, }; -use crate::devices::virtio::gen::virtio_ring::VIRTIO_RING_F_EVENT_IDX; +use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::vhost_user::{VhostUserHandleBackend, VhostUserHandleImpl}; use crate::devices::virtio::vhost_user_metrics::{ diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index 5854fd8598f..b8d8d588a56 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -24,10 +24,10 @@ use super::{io as block_io, VirtioBlockError, BLOCK_QUEUE_SIZES, SECTOR_SHIFT, S use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice}; use crate::devices::virtio::block::CacheType; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::gen::virtio_blk::{ +use crate::devices::virtio::generated::virtio_blk::{ VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_BLK_ID_BYTES, VIRTIO_F_VERSION_1, }; -use crate::devices::virtio::gen::virtio_ring::VIRTIO_RING_F_EVENT_IDX; +use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::{ActivateError, TYPE_BLOCK}; use crate::logger::{error, warn, IncMetric}; diff --git a/src/vmm/src/devices/virtio/block/virtio/persist.rs b/src/vmm/src/devices/virtio/block/virtio/persist.rs index caab2c13a5f..ceceadb3ad9 100644 --- a/src/vmm/src/devices/virtio/block/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/block/virtio/persist.rs @@ -16,7 +16,7 @@ use crate::devices::virtio::block::persist::BlockConstructorArgs; use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::block::virtio::metrics::BlockMetricsPerDevice; use crate::devices::virtio::device::{DeviceState, IrqTrigger}; -use crate::devices::virtio::gen::virtio_blk::VIRTIO_BLK_F_RO; +use crate::devices::virtio::generated::virtio_blk::VIRTIO_BLK_F_RO; use crate::devices::virtio::persist::VirtioDeviceState; use crate::devices::virtio::TYPE_BLOCK; use crate::rate_limiter::persist::RateLimiterState; diff --git a/src/vmm/src/devices/virtio/block/virtio/request.rs b/src/vmm/src/devices/virtio/block/virtio/request.rs index 27df7c1d675..8695ad4229e 100644 --- a/src/vmm/src/devices/virtio/block/virtio/request.rs +++ b/src/vmm/src/devices/virtio/block/virtio/request.rs @@ -12,7 +12,7 @@ use vm_memory::GuestMemoryError; use super::{io as block_io, VirtioBlockError, SECTOR_SHIFT, SECTOR_SIZE}; use crate::devices::virtio::block::virtio::device::DiskProperties; use crate::devices::virtio::block::virtio::metrics::BlockDeviceMetrics; -pub use crate::devices::virtio::gen::virtio_blk::{ +pub use crate::devices::virtio::generated::virtio_blk::{ VIRTIO_BLK_ID_BYTES, VIRTIO_BLK_S_IOERR, VIRTIO_BLK_S_OK, VIRTIO_BLK_S_UNSUPP, VIRTIO_BLK_T_FLUSH, VIRTIO_BLK_T_GET_ID, VIRTIO_BLK_T_IN, VIRTIO_BLK_T_OUT, }; diff --git a/src/vmm/src/devices/virtio/gen/virtio_net.rs b/src/vmm/src/devices/virtio/gen/virtio_net.rs deleted file mode 100644 index 156e25497fe..00000000000 --- a/src/vmm/src/devices/virtio/gen/virtio_net.rs +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2024 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 -)] - -pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; -pub const VIRTIO_F_ANY_LAYOUT: u32 = 27; -pub const VIRTIO_F_VERSION_1: u32 = 32; -pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; -pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; -pub const VIRTIO_F_RING_PACKED: u32 = 34; -pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; -pub const VIRTIO_F_SR_IOV: u32 = 37; -pub const VIRTIO_NET_F_CSUM: u32 = 0; -pub const VIRTIO_NET_F_GUEST_CSUM: u32 = 1; -pub const VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: u32 = 2; -pub const VIRTIO_NET_F_MTU: u32 = 3; -pub const VIRTIO_NET_F_MAC: u32 = 5; -pub const VIRTIO_NET_F_GUEST_TSO4: u32 = 7; -pub const VIRTIO_NET_F_GUEST_TSO6: u32 = 8; -pub const VIRTIO_NET_F_GUEST_ECN: u32 = 9; -pub const VIRTIO_NET_F_GUEST_UFO: u32 = 10; -pub const VIRTIO_NET_F_HOST_TSO4: u32 = 11; -pub const VIRTIO_NET_F_HOST_TSO6: u32 = 12; -pub const VIRTIO_NET_F_HOST_ECN: u32 = 13; -pub const VIRTIO_NET_F_HOST_UFO: u32 = 14; -pub const VIRTIO_NET_F_MRG_RXBUF: u32 = 15; -pub const VIRTIO_NET_F_STATUS: u32 = 16; -pub const VIRTIO_NET_F_CTRL_VQ: u32 = 17; -pub const VIRTIO_NET_F_CTRL_RX: u32 = 18; -pub const VIRTIO_NET_F_CTRL_VLAN: u32 = 19; -pub const VIRTIO_NET_F_CTRL_RX_EXTRA: u32 = 20; -pub const VIRTIO_NET_F_GUEST_ANNOUNCE: u32 = 21; -pub const VIRTIO_NET_F_MQ: u32 = 22; -pub const VIRTIO_NET_F_CTRL_MAC_ADDR: u32 = 23; -pub const VIRTIO_NET_F_HASH_REPORT: u32 = 57; -pub const VIRTIO_NET_F_RSS: u32 = 60; -pub const VIRTIO_NET_F_RSC_EXT: u32 = 61; -pub const VIRTIO_NET_F_STANDBY: u32 = 62; -pub const VIRTIO_NET_F_SPEED_DUPLEX: u32 = 63; -pub const VIRTIO_NET_F_GSO: u32 = 6; -pub type __u8 = ::std::os::raw::c_uchar; -pub type __u16 = ::std::os::raw::c_ushort; -pub type __le16 = __u16; -pub type __virtio16 = __u16; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct virtio_net_hdr_v1 { - pub flags: __u8, - pub gso_type: __u8, - pub hdr_len: __virtio16, - pub gso_size: __virtio16, - pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1, - pub num_buffers: __virtio16, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union virtio_net_hdr_v1__bindgen_ty_1 { - pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1, - pub csum: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2, - pub rsc: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3, -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1 { - pub csum_start: __virtio16, - pub csum_offset: __virtio16, -} -#[test] -fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).csum_start) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(csum_start) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).csum_offset) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(csum_offset) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2 { - pub start: __virtio16, - pub offset: __virtio16, -} -#[test] -fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).start) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(start) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2), - "::", - stringify!(offset) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3 { - pub segments: __le16, - pub dup_acks: __le16, -} -#[test] -fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!( - "Size of: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!( - "Alignment of ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).segments) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3), - "::", - stringify!(segments) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dup_acks) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3), - "::", - stringify!(dup_acks) - ) - ); -} -#[test] -fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(virtio_net_hdr_v1__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(virtio_net_hdr_v1__bindgen_ty_1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).csum) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1), - "::", - stringify!(csum) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rsc) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1__bindgen_ty_1), - "::", - stringify!(rsc) - ) - ); -} -impl Default for virtio_net_hdr_v1__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() - } - } -} -#[test] -fn bindgen_test_layout_virtio_net_hdr_v1() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(virtio_net_hdr_v1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(virtio_net_hdr_v1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).gso_type) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1), - "::", - stringify!(gso_type) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).hdr_len) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1), - "::", - stringify!(hdr_len) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).gso_size) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1), - "::", - stringify!(gso_size) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).num_buffers) as usize - ptr as usize }, - 10usize, - concat!( - "Offset of field: ", - stringify!(virtio_net_hdr_v1), - "::", - stringify!(num_buffers) - ) - ); -} -impl Default for virtio_net_hdr_v1 { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} diff --git a/src/vmm/src/devices/virtio/gen/mod.rs b/src/vmm/src/devices/virtio/generated/mod.rs similarity index 100% rename from src/vmm/src/devices/virtio/gen/mod.rs rename to src/vmm/src/devices/virtio/generated/mod.rs diff --git a/src/vmm/src/devices/virtio/gen/virtio_blk.rs b/src/vmm/src/devices/virtio/generated/virtio_blk.rs similarity index 53% rename from src/vmm/src/devices/virtio/gen/virtio_blk.rs rename to src/vmm/src/devices/virtio/generated/virtio_blk.rs index 7ef2b55ec21..635861506cf 100644 --- a/src/vmm/src/devices/virtio/gen/virtio_blk.rs +++ b/src/vmm/src/devices/virtio/generated/virtio_blk.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; @@ -20,8 +21,13 @@ pub const VIRTIO_F_VERSION_1: u32 = 32; pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; pub const VIRTIO_F_RING_PACKED: u32 = 34; +pub const VIRTIO_F_IN_ORDER: u32 = 35; pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; pub const VIRTIO_F_SR_IOV: u32 = 37; +pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; +pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; +pub const VIRTIO_F_RING_RESET: u32 = 40; +pub const VIRTIO_F_ADMIN_VQ: u32 = 41; pub const VIRTIO_BLK_F_SIZE_MAX: u32 = 1; pub const VIRTIO_BLK_F_SEG_MAX: u32 = 2; pub const VIRTIO_BLK_F_GEOMETRY: u32 = 4; @@ -31,6 +37,8 @@ pub const VIRTIO_BLK_F_TOPOLOGY: u32 = 10; pub const VIRTIO_BLK_F_MQ: u32 = 12; pub const VIRTIO_BLK_F_DISCARD: u32 = 13; pub const VIRTIO_BLK_F_WRITE_ZEROES: u32 = 14; +pub const VIRTIO_BLK_F_SECURE_ERASE: u32 = 16; +pub const VIRTIO_BLK_F_ZONED: u32 = 17; pub const VIRTIO_BLK_F_BARRIER: u32 = 0; pub const VIRTIO_BLK_F_SCSI: u32 = 7; pub const VIRTIO_BLK_F_FLUSH: u32 = 9; @@ -44,8 +52,34 @@ pub const VIRTIO_BLK_T_FLUSH: u32 = 4; pub const VIRTIO_BLK_T_GET_ID: u32 = 8; pub const VIRTIO_BLK_T_DISCARD: u32 = 11; pub const VIRTIO_BLK_T_WRITE_ZEROES: u32 = 13; +pub const VIRTIO_BLK_T_SECURE_ERASE: u32 = 14; +pub const VIRTIO_BLK_T_ZONE_APPEND: u32 = 15; +pub const VIRTIO_BLK_T_ZONE_REPORT: u32 = 16; +pub const VIRTIO_BLK_T_ZONE_OPEN: u32 = 18; +pub const VIRTIO_BLK_T_ZONE_CLOSE: u32 = 20; +pub const VIRTIO_BLK_T_ZONE_FINISH: u32 = 22; +pub const VIRTIO_BLK_T_ZONE_RESET: u32 = 24; +pub const VIRTIO_BLK_T_ZONE_RESET_ALL: u32 = 26; pub const VIRTIO_BLK_T_BARRIER: u32 = 2147483648; +pub const VIRTIO_BLK_Z_NONE: u32 = 0; +pub const VIRTIO_BLK_Z_HM: u32 = 1; +pub const VIRTIO_BLK_Z_HA: u32 = 2; +pub const VIRTIO_BLK_ZT_CONV: u32 = 1; +pub const VIRTIO_BLK_ZT_SWR: u32 = 2; +pub const VIRTIO_BLK_ZT_SWP: u32 = 3; +pub const VIRTIO_BLK_ZS_NOT_WP: u32 = 0; +pub const VIRTIO_BLK_ZS_EMPTY: u32 = 1; +pub const VIRTIO_BLK_ZS_IOPEN: u32 = 2; +pub const VIRTIO_BLK_ZS_EOPEN: u32 = 3; +pub const VIRTIO_BLK_ZS_CLOSED: u32 = 4; +pub const VIRTIO_BLK_ZS_RDONLY: u32 = 13; +pub const VIRTIO_BLK_ZS_FULL: u32 = 14; +pub const VIRTIO_BLK_ZS_OFFLINE: u32 = 15; pub const VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP: u32 = 1; pub const VIRTIO_BLK_S_OK: u32 = 0; pub const VIRTIO_BLK_S_IOERR: u32 = 1; pub const VIRTIO_BLK_S_UNSUPP: u32 = 2; +pub const VIRTIO_BLK_S_ZONE_INVALID_CMD: u32 = 3; +pub const VIRTIO_BLK_S_ZONE_UNALIGNED_WP: u32 = 4; +pub const VIRTIO_BLK_S_ZONE_OPEN_RESOURCE: u32 = 5; +pub const VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE: u32 = 6; diff --git a/src/vmm/src/devices/virtio/generated/virtio_net.rs b/src/vmm/src/devices/virtio/generated/virtio_net.rs new file mode 100644 index 00000000000..839cbd8b782 --- /dev/null +++ b/src/vmm/src/devices/virtio/generated/virtio_net.rs @@ -0,0 +1,184 @@ +// 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 +)] + +pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; +pub const VIRTIO_F_ANY_LAYOUT: u32 = 27; +pub const VIRTIO_F_VERSION_1: u32 = 32; +pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; +pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; +pub const VIRTIO_F_RING_PACKED: u32 = 34; +pub const VIRTIO_F_IN_ORDER: u32 = 35; +pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; +pub const VIRTIO_F_SR_IOV: u32 = 37; +pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; +pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; +pub const VIRTIO_F_RING_RESET: u32 = 40; +pub const VIRTIO_F_ADMIN_VQ: u32 = 41; +pub const VIRTIO_NET_F_CSUM: u32 = 0; +pub const VIRTIO_NET_F_GUEST_CSUM: u32 = 1; +pub const VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: u32 = 2; +pub const VIRTIO_NET_F_MTU: u32 = 3; +pub const VIRTIO_NET_F_MAC: u32 = 5; +pub const VIRTIO_NET_F_GUEST_TSO4: u32 = 7; +pub const VIRTIO_NET_F_GUEST_TSO6: u32 = 8; +pub const VIRTIO_NET_F_GUEST_ECN: u32 = 9; +pub const VIRTIO_NET_F_GUEST_UFO: u32 = 10; +pub const VIRTIO_NET_F_HOST_TSO4: u32 = 11; +pub const VIRTIO_NET_F_HOST_TSO6: u32 = 12; +pub const VIRTIO_NET_F_HOST_ECN: u32 = 13; +pub const VIRTIO_NET_F_HOST_UFO: u32 = 14; +pub const VIRTIO_NET_F_MRG_RXBUF: u32 = 15; +pub const VIRTIO_NET_F_STATUS: u32 = 16; +pub const VIRTIO_NET_F_CTRL_VQ: u32 = 17; +pub const VIRTIO_NET_F_CTRL_RX: u32 = 18; +pub const VIRTIO_NET_F_CTRL_VLAN: u32 = 19; +pub const VIRTIO_NET_F_CTRL_RX_EXTRA: u32 = 20; +pub const VIRTIO_NET_F_GUEST_ANNOUNCE: u32 = 21; +pub const VIRTIO_NET_F_MQ: u32 = 22; +pub const VIRTIO_NET_F_CTRL_MAC_ADDR: u32 = 23; +pub const VIRTIO_NET_F_VQ_NOTF_COAL: u32 = 52; +pub const VIRTIO_NET_F_NOTF_COAL: u32 = 53; +pub const VIRTIO_NET_F_GUEST_USO4: u32 = 54; +pub const VIRTIO_NET_F_GUEST_USO6: u32 = 55; +pub const VIRTIO_NET_F_HOST_USO: u32 = 56; +pub const VIRTIO_NET_F_HASH_REPORT: u32 = 57; +pub const VIRTIO_NET_F_GUEST_HDRLEN: u32 = 59; +pub const VIRTIO_NET_F_RSS: u32 = 60; +pub const VIRTIO_NET_F_RSC_EXT: u32 = 61; +pub const VIRTIO_NET_F_STANDBY: u32 = 62; +pub const VIRTIO_NET_F_SPEED_DUPLEX: u32 = 63; +pub const VIRTIO_NET_F_GSO: u32 = 6; +pub type __u8 = ::std::os::raw::c_uchar; +pub type __u16 = ::std::os::raw::c_ushort; +pub type __le16 = __u16; +pub type __virtio16 = __u16; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct virtio_net_hdr_v1 { + pub flags: __u8, + pub gso_type: __u8, + pub hdr_len: __virtio16, + pub gso_size: __virtio16, + pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1, + pub num_buffers: __virtio16, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union virtio_net_hdr_v1__bindgen_ty_1 { + pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1, + pub csum: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2, + pub rsc: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3, +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1 { + pub csum_start: __virtio16, + pub csum_offset: __virtio16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1::csum_start"][::std::mem::offset_of!( + virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1, + csum_start + ) - 0usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1::csum_offset"][::std::mem::offset_of!( + virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1, + csum_offset + ) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2 { + pub start: __virtio16, + pub offset: __virtio16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2::start"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2, start) - 0usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2::offset"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2, offset) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3 { + pub segments: __le16, + pub dup_acks: __le16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3::segments"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3, segments) - 0usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3::dup_acks"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3, dup_acks) - 2usize]; +}; +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_net_hdr_v1__bindgen_ty_1"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of virtio_net_hdr_v1__bindgen_ty_1"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1::csum"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1, csum) - 0usize]; + ["Offset of field: virtio_net_hdr_v1__bindgen_ty_1::rsc"] + [::std::mem::offset_of!(virtio_net_hdr_v1__bindgen_ty_1, rsc) - 0usize]; +}; +impl Default for virtio_net_hdr_v1__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_net_hdr_v1"][::std::mem::size_of::() - 12usize]; + ["Alignment of virtio_net_hdr_v1"][::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_net_hdr_v1::flags"] + [::std::mem::offset_of!(virtio_net_hdr_v1, flags) - 0usize]; + ["Offset of field: virtio_net_hdr_v1::gso_type"] + [::std::mem::offset_of!(virtio_net_hdr_v1, gso_type) - 1usize]; + ["Offset of field: virtio_net_hdr_v1::hdr_len"] + [::std::mem::offset_of!(virtio_net_hdr_v1, hdr_len) - 2usize]; + ["Offset of field: virtio_net_hdr_v1::gso_size"] + [::std::mem::offset_of!(virtio_net_hdr_v1, gso_size) - 4usize]; + ["Offset of field: virtio_net_hdr_v1::num_buffers"] + [::std::mem::offset_of!(virtio_net_hdr_v1, num_buffers) - 10usize]; +}; +impl Default for virtio_net_hdr_v1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/src/vmm/src/devices/virtio/gen/virtio_ring.rs b/src/vmm/src/devices/virtio/generated/virtio_ring.rs similarity index 72% rename from src/vmm/src/devices/virtio/gen/virtio_ring.rs rename to src/vmm/src/devices/virtio/generated/virtio_ring.rs index 9d228ea9ee8..a0411fcc92b 100644 --- a/src/vmm/src/devices/virtio/gen/virtio_ring.rs +++ b/src/vmm/src/devices/virtio/generated/virtio_ring.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const VIRTIO_RING_F_EVENT_IDX: u32 = 29; diff --git a/src/vmm/src/devices/virtio/gen/virtio_rng.rs b/src/vmm/src/devices/virtio/generated/virtio_rng.rs similarity index 65% rename from src/vmm/src/devices/virtio/gen/virtio_rng.rs rename to src/vmm/src/devices/virtio/generated/virtio_rng.rs index a0f43120693..e1ecc4fa38b 100644 --- a/src/vmm/src/devices/virtio/gen/virtio_rng.rs +++ b/src/vmm/src/devices/virtio/generated/virtio_rng.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; @@ -20,5 +21,10 @@ pub const VIRTIO_F_VERSION_1: u32 = 32; pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; pub const VIRTIO_F_RING_PACKED: u32 = 34; +pub const VIRTIO_F_IN_ORDER: u32 = 35; pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; pub const VIRTIO_F_SR_IOV: u32 = 37; +pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; +pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; +pub const VIRTIO_F_RING_RESET: u32 = 40; +pub const VIRTIO_F_ADMIN_VQ: u32 = 41; diff --git a/src/vmm/src/devices/virtio/mod.rs b/src/vmm/src/devices/virtio/mod.rs index 9931e1211d1..f298d28e9bd 100644 --- a/src/vmm/src/devices/virtio/mod.rs +++ b/src/vmm/src/devices/virtio/mod.rs @@ -15,7 +15,7 @@ use crate::devices::virtio::net::TapError; pub mod balloon; pub mod block; pub mod device; -pub mod gen; +pub mod generated; mod iov_deque; pub mod iovec; pub mod mmio; diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 5b8e21ac21a..885abb812f0 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -16,20 +16,20 @@ use vmm_sys_util::eventfd::EventFd; use super::NET_QUEUE_MAX_SIZE; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::gen::virtio_blk::VIRTIO_F_VERSION_1; -use crate::devices::virtio::gen::virtio_net::{ +use crate::devices::virtio::generated::virtio_blk::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_net::{ virtio_net_hdr_v1, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MRG_RXBUF, }; -use crate::devices::virtio::gen::virtio_ring::VIRTIO_RING_F_EVENT_IDX; +use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::iovec::{ IoVecBuffer, IoVecBufferMut, IoVecError, ParsedDescriptorChain, }; use crate::devices::virtio::net::metrics::{NetDeviceMetrics, NetMetricsPerDevice}; use crate::devices::virtio::net::tap::Tap; use crate::devices::virtio::net::{ - gen, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX, + generated, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX, }; use crate::devices::virtio::queue::{DescriptorChain, Queue}; use crate::devices::virtio::{ActivateError, TYPE_NET}; @@ -778,25 +778,25 @@ impl Net { add_if_supported( &mut tap_features, guest_supported_features, - gen::TUN_F_CSUM, + generated::TUN_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, ); add_if_supported( &mut tap_features, guest_supported_features, - gen::TUN_F_UFO, + generated::TUN_F_UFO, VIRTIO_NET_F_GUEST_UFO, ); add_if_supported( &mut tap_features, guest_supported_features, - gen::TUN_F_TSO4, + generated::TUN_F_TSO4, VIRTIO_NET_F_GUEST_TSO4, ); add_if_supported( &mut tap_features, guest_supported_features, - gen::TUN_F_TSO6, + generated::TUN_F_TSO6, VIRTIO_NET_F_GUEST_TSO6, ); @@ -1040,7 +1040,7 @@ pub mod tests { use super::*; use crate::check_metric_after_block; - use crate::devices::virtio::gen::virtio_ring::VIRTIO_RING_F_EVENT_IDX; + use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::iovec::IoVecBuffer; use crate::devices::virtio::net::device::{ frame_bytes_from_buf, frame_bytes_from_buf_mut, frame_hdr_len, init_vnet_hdr, vnet_hdr_len, @@ -1154,7 +1154,7 @@ pub mod tests { | (1 << VIRTIO_NET_F_GUEST_TSO4) | (1 << VIRTIO_NET_F_GUEST_TSO6); let expected_tap_features = - gen::TUN_F_CSUM | gen::TUN_F_UFO | gen::TUN_F_TSO4 | gen::TUN_F_TSO6; + generated::TUN_F_CSUM | generated::TUN_F_UFO | generated::TUN_F_TSO4 | generated::TUN_F_TSO6; let supported_flags = Net::build_tap_offload_features(supported_features); assert_eq!(supported_flags, expected_tap_features); @@ -1164,9 +1164,9 @@ pub mod tests { // Same as before, however, using each supported feature one by one. fn test_build_tap_offload_features_one_by_one() { let features = [ - (1 << VIRTIO_NET_F_GUEST_CSUM, gen::TUN_F_CSUM), - (1 << VIRTIO_NET_F_GUEST_UFO, gen::TUN_F_UFO), - (1 << VIRTIO_NET_F_GUEST_TSO4, gen::TUN_F_TSO4), + (1 << VIRTIO_NET_F_GUEST_CSUM, generated::TUN_F_CSUM), + (1 << VIRTIO_NET_F_GUEST_UFO, generated::TUN_F_UFO), + (1 << VIRTIO_NET_F_GUEST_TSO4, generated::TUN_F_TSO4), ]; for (virtio_flag, tap_flag) in features { let supported_flags = Net::build_tap_offload_features(virtio_flag); diff --git a/src/vmm/src/devices/virtio/net/gen/iff.rs b/src/vmm/src/devices/virtio/net/gen/iff.rs deleted file mode 100644 index 868c61cda73..00000000000 --- a/src/vmm/src/devices/virtio/net/gen/iff.rs +++ /dev/null @@ -1,1187 +0,0 @@ -// Copyright 2024 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 -)] - -pub const IFNAMSIZ: u32 = 16; -pub const IFALIASZ: u32 = 256; -pub const IF_GET_IFACE: u32 = 1; -pub const IF_GET_PROTO: u32 = 2; -pub const IF_IFACE_V35: u32 = 4096; -pub const IF_IFACE_V24: u32 = 4097; -pub const IF_IFACE_X21: u32 = 4098; -pub const IF_IFACE_T1: u32 = 4099; -pub const IF_IFACE_E1: u32 = 4100; -pub const IF_IFACE_SYNC_SERIAL: u32 = 4101; -pub const IF_IFACE_X21D: u32 = 4102; -pub const IF_PROTO_HDLC: u32 = 8192; -pub const IF_PROTO_PPP: u32 = 8193; -pub const IF_PROTO_CISCO: u32 = 8194; -pub const IF_PROTO_FR: u32 = 8195; -pub const IF_PROTO_FR_ADD_PVC: u32 = 8196; -pub const IF_PROTO_FR_DEL_PVC: u32 = 8197; -pub const IF_PROTO_X25: u32 = 8198; -pub const IF_PROTO_HDLC_ETH: u32 = 8199; -pub const IF_PROTO_FR_ADD_ETH_PVC: u32 = 8200; -pub const IF_PROTO_FR_DEL_ETH_PVC: u32 = 8201; -pub const IF_PROTO_FR_PVC: u32 = 8202; -pub const IF_PROTO_FR_ETH_PVC: u32 = 8203; -pub const IF_PROTO_RAW: u32 = 8204; -pub const IFHWADDRLEN: u32 = 6; -pub type sa_family_t = ::std::os::raw::c_ushort; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct sockaddr { - pub sa_family: sa_family_t, - pub sa_data: [::std::os::raw::c_char; 14usize], -} -#[test] -fn bindgen_test_layout_sockaddr() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(sockaddr)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(sockaddr)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sa_family) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sockaddr), - "::", - stringify!(sa_family) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sa_data) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(sockaddr), - "::", - stringify!(sa_data) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct sync_serial_settings { - pub clock_rate: ::std::os::raw::c_uint, - pub clock_type: ::std::os::raw::c_uint, - pub loopback: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_sync_serial_settings() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(sync_serial_settings)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(sync_serial_settings)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).clock_rate) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sync_serial_settings), - "::", - stringify!(clock_rate) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).clock_type) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(sync_serial_settings), - "::", - stringify!(clock_type) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).loopback) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(sync_serial_settings), - "::", - stringify!(loopback) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct te1_settings { - pub clock_rate: ::std::os::raw::c_uint, - pub clock_type: ::std::os::raw::c_uint, - pub loopback: ::std::os::raw::c_ushort, - pub slot_map: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_te1_settings() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(te1_settings)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(te1_settings)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).clock_rate) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(te1_settings), - "::", - stringify!(clock_rate) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).clock_type) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(te1_settings), - "::", - stringify!(clock_type) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).loopback) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(te1_settings), - "::", - stringify!(loopback) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).slot_map) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(te1_settings), - "::", - stringify!(slot_map) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct raw_hdlc_proto { - pub encoding: ::std::os::raw::c_ushort, - pub parity: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_raw_hdlc_proto() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(raw_hdlc_proto)) - ); - assert_eq!( - ::std::mem::align_of::(), - 2usize, - concat!("Alignment of ", stringify!(raw_hdlc_proto)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).encoding) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(raw_hdlc_proto), - "::", - stringify!(encoding) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).parity) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(raw_hdlc_proto), - "::", - stringify!(parity) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct fr_proto { - pub t391: ::std::os::raw::c_uint, - pub t392: ::std::os::raw::c_uint, - pub n391: ::std::os::raw::c_uint, - pub n392: ::std::os::raw::c_uint, - pub n393: ::std::os::raw::c_uint, - pub lmi: ::std::os::raw::c_ushort, - pub dce: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_fr_proto() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(fr_proto)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(fr_proto)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).t391) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(t391) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).t392) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(t392) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).n391) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(n391) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).n392) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(n392) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).n393) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(n393) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).lmi) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(lmi) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dce) as usize - ptr as usize }, - 22usize, - concat!( - "Offset of field: ", - stringify!(fr_proto), - "::", - stringify!(dce) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct fr_proto_pvc { - pub dlci: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_fr_proto_pvc() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(fr_proto_pvc)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(fr_proto_pvc)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dlci) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(fr_proto_pvc), - "::", - stringify!(dlci) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct fr_proto_pvc_info { - pub dlci: ::std::os::raw::c_uint, - pub master: [::std::os::raw::c_char; 16usize], -} -#[test] -fn bindgen_test_layout_fr_proto_pvc_info() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(fr_proto_pvc_info)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(fr_proto_pvc_info)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dlci) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(fr_proto_pvc_info), - "::", - stringify!(dlci) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).master) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(fr_proto_pvc_info), - "::", - stringify!(master) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct cisco_proto { - pub interval: ::std::os::raw::c_uint, - pub timeout: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_cisco_proto() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(cisco_proto)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(cisco_proto)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).interval) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cisco_proto), - "::", - stringify!(interval) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(cisco_proto), - "::", - stringify!(timeout) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct x25_hdlc_proto { - pub dce: ::std::os::raw::c_ushort, - pub modulo: ::std::os::raw::c_uint, - pub window: ::std::os::raw::c_uint, - pub t1: ::std::os::raw::c_uint, - pub t2: ::std::os::raw::c_uint, - pub n2: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_x25_hdlc_proto() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(x25_hdlc_proto)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(x25_hdlc_proto)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dce) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(dce) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).modulo) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(modulo) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).window) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(window) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).t1) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(t1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).t2) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(t2) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).n2) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(x25_hdlc_proto), - "::", - stringify!(n2) - ) - ); -} -pub const net_device_flags_IFF_UP: net_device_flags = 1; -pub const net_device_flags_IFF_BROADCAST: net_device_flags = 2; -pub const net_device_flags_IFF_DEBUG: net_device_flags = 4; -pub const net_device_flags_IFF_LOOPBACK: net_device_flags = 8; -pub const net_device_flags_IFF_POINTOPOINT: net_device_flags = 16; -pub const net_device_flags_IFF_NOTRAILERS: net_device_flags = 32; -pub const net_device_flags_IFF_RUNNING: net_device_flags = 64; -pub const net_device_flags_IFF_NOARP: net_device_flags = 128; -pub const net_device_flags_IFF_PROMISC: net_device_flags = 256; -pub const net_device_flags_IFF_ALLMULTI: net_device_flags = 512; -pub const net_device_flags_IFF_MASTER: net_device_flags = 1024; -pub const net_device_flags_IFF_SLAVE: net_device_flags = 2048; -pub const net_device_flags_IFF_MULTICAST: net_device_flags = 4096; -pub const net_device_flags_IFF_PORTSEL: net_device_flags = 8192; -pub const net_device_flags_IFF_AUTOMEDIA: net_device_flags = 16384; -pub const net_device_flags_IFF_DYNAMIC: net_device_flags = 32768; -pub const net_device_flags_IFF_LOWER_UP: net_device_flags = 65536; -pub const net_device_flags_IFF_DORMANT: net_device_flags = 131072; -pub const net_device_flags_IFF_ECHO: net_device_flags = 262144; -pub type net_device_flags = ::std::os::raw::c_uint; -pub const IF_OPER_UNKNOWN: _bindgen_ty_4 = 0; -pub const IF_OPER_NOTPRESENT: _bindgen_ty_4 = 1; -pub const IF_OPER_DOWN: _bindgen_ty_4 = 2; -pub const IF_OPER_LOWERLAYERDOWN: _bindgen_ty_4 = 3; -pub const IF_OPER_TESTING: _bindgen_ty_4 = 4; -pub const IF_OPER_DORMANT: _bindgen_ty_4 = 5; -pub const IF_OPER_UP: _bindgen_ty_4 = 6; -pub type _bindgen_ty_4 = ::std::os::raw::c_uint; -pub const IF_LINK_MODE_DEFAULT: _bindgen_ty_5 = 0; -pub const IF_LINK_MODE_DORMANT: _bindgen_ty_5 = 1; -pub const IF_LINK_MODE_TESTING: _bindgen_ty_5 = 2; -pub type _bindgen_ty_5 = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct ifmap { - pub mem_start: ::std::os::raw::c_ulong, - pub mem_end: ::std::os::raw::c_ulong, - pub base_addr: ::std::os::raw::c_ushort, - pub irq: ::std::os::raw::c_uchar, - pub dma: ::std::os::raw::c_uchar, - pub port: ::std::os::raw::c_uchar, -} -#[test] -fn bindgen_test_layout_ifmap() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(ifmap)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ifmap)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mem_start) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(mem_start) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mem_end) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(mem_end) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).base_addr) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(base_addr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).irq) as usize - ptr as usize }, - 18usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(irq) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dma) as usize - ptr as usize }, - 19usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(dma) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(ifmap), - "::", - stringify!(port) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct if_settings { - pub type_: ::std::os::raw::c_uint, - pub size: ::std::os::raw::c_uint, - pub ifs_ifsu: if_settings__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union if_settings__bindgen_ty_1 { - pub raw_hdlc: *mut raw_hdlc_proto, - pub cisco: *mut cisco_proto, - pub fr: *mut fr_proto, - pub fr_pvc: *mut fr_proto_pvc, - pub fr_pvc_info: *mut fr_proto_pvc_info, - pub x25: *mut x25_hdlc_proto, - pub sync: *mut sync_serial_settings, - pub te1: *mut te1_settings, -} -#[test] -fn bindgen_test_layout_if_settings__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(if_settings__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(if_settings__bindgen_ty_1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).raw_hdlc) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(raw_hdlc) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cisco) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(cisco) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(fr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fr_pvc) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(fr_pvc) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fr_pvc_info) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(fr_pvc_info) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).x25) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(x25) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sync) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(sync) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).te1) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings__bindgen_ty_1), - "::", - stringify!(te1) - ) - ); -} -impl Default for if_settings__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() - } - } -} -#[test] -fn bindgen_test_layout_if_settings() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(if_settings)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(if_settings)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(if_settings), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(if_settings), - "::", - stringify!(size) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifs_ifsu) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(if_settings), - "::", - stringify!(ifs_ifsu) - ) - ); -} -impl Default for if_settings { - 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(Copy, Clone)] -pub struct ifreq { - pub ifr_ifrn: ifreq__bindgen_ty_1, - pub ifr_ifru: ifreq__bindgen_ty_2, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifreq__bindgen_ty_1 { - pub ifrn_name: [::std::os::raw::c_uchar; 16usize], -} -#[test] -fn bindgen_test_layout_ifreq__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ifreq__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(ifreq__bindgen_ty_1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifrn_name) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_1), - "::", - stringify!(ifrn_name) - ) - ); -} -impl Default for ifreq__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() - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifreq__bindgen_ty_2 { - pub ifru_addr: sockaddr, - pub ifru_dstaddr: sockaddr, - pub ifru_broadaddr: sockaddr, - pub ifru_netmask: sockaddr, - pub ifru_hwaddr: sockaddr, - pub ifru_flags: ::std::os::raw::c_short, - pub ifru_ivalue: ::std::os::raw::c_int, - pub ifru_mtu: ::std::os::raw::c_int, - pub ifru_map: ifmap, - pub ifru_slave: [::std::os::raw::c_char; 16usize], - pub ifru_newname: [::std::os::raw::c_char; 16usize], - pub ifru_data: *mut ::std::os::raw::c_void, - pub ifru_settings: if_settings, -} -#[test] -fn bindgen_test_layout_ifreq__bindgen_ty_2() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(ifreq__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ifreq__bindgen_ty_2)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_addr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_addr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_dstaddr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_dstaddr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_broadaddr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_broadaddr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_netmask) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_netmask) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_hwaddr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_hwaddr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_ivalue) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_ivalue) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_mtu) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_mtu) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_map) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_map) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_slave) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_slave) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_newname) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_newname) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_data) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifru_settings) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq__bindgen_ty_2), - "::", - stringify!(ifru_settings) - ) - ); -} -impl Default for ifreq__bindgen_ty_2 { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} -#[test] -fn bindgen_test_layout_ifreq() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(ifreq)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ifreq)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifr_ifrn) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifreq), - "::", - stringify!(ifr_ifrn) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifr_ifru) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(ifreq), - "::", - stringify!(ifr_ifru) - ) - ); -} -impl Default for ifreq { - 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(Copy, Clone)] -pub struct ifconf { - pub ifc_len: ::std::os::raw::c_int, - pub ifc_ifcu: ifconf__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifconf__bindgen_ty_1 { - pub ifcu_buf: *mut ::std::os::raw::c_char, - pub ifcu_req: *mut ifreq, -} -#[test] -fn bindgen_test_layout_ifconf__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(ifconf__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ifconf__bindgen_ty_1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifcu_buf) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifconf__bindgen_ty_1), - "::", - stringify!(ifcu_buf) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifcu_req) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifconf__bindgen_ty_1), - "::", - stringify!(ifcu_req) - ) - ); -} -impl Default for ifconf__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() - } - } -} -#[test] -fn bindgen_test_layout_ifconf() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ifconf)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ifconf)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifc_len) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ifconf), - "::", - stringify!(ifc_len) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ifc_ifcu) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ifconf), - "::", - stringify!(ifc_ifcu) - ) - ); -} -impl Default for ifconf { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} diff --git a/src/vmm/src/devices/virtio/net/gen/if_tun.rs b/src/vmm/src/devices/virtio/net/generated/if_tun.rs similarity index 66% rename from src/vmm/src/devices/virtio/net/gen/if_tun.rs rename to src/vmm/src/devices/virtio/net/generated/if_tun.rs index 7b994a327c1..d08fe1b1ce7 100644 --- a/src/vmm/src/devices/virtio/net/gen/if_tun.rs +++ b/src/vmm/src/devices/virtio/net/generated/if_tun.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const ETH_ALEN: u32 = 6; @@ -62,7 +63,10 @@ pub const ETH_P_PPP_SES: u32 = 34916; pub const ETH_P_LINK_CTL: u32 = 34924; pub const ETH_P_ATMFATE: u32 = 34948; pub const ETH_P_PAE: u32 = 34958; +pub const ETH_P_PROFINET: u32 = 34962; +pub const ETH_P_REALTEK: u32 = 34969; pub const ETH_P_AOE: u32 = 34978; +pub const ETH_P_ETHERCAT: u32 = 34980; pub const ETH_P_8021AD: u32 = 34984; pub const ETH_P_802_EX1: u32 = 34997; pub const ETH_P_PREAUTH: u32 = 35015; @@ -89,6 +93,7 @@ pub const ETH_P_QINQ2: u32 = 37376; pub const ETH_P_QINQ3: u32 = 37632; pub const ETH_P_EDSA: u32 = 56026; pub const ETH_P_DSA_8021Q: u32 = 56027; +pub const ETH_P_DSA_A5PSW: u32 = 57345; pub const ETH_P_IFE: u32 = 60734; pub const ETH_P_AF_IUCV: u32 = 64507; pub const ETH_P_802_3_MIN: u32 = 1536; @@ -103,6 +108,7 @@ pub const ETH_P_PPP_MP: u32 = 8; pub const ETH_P_LOCALTALK: u32 = 9; pub const ETH_P_CAN: u32 = 12; pub const ETH_P_CANFD: u32 = 13; +pub const ETH_P_CANXL: u32 = 14; pub const ETH_P_PPPTALK: u32 = 16; pub const ETH_P_TR_802_2: u32 = 17; pub const ETH_P_MOBITEX: u32 = 21; @@ -131,6 +137,8 @@ pub const TUN_F_TSO4: u32 = 2; pub const TUN_F_TSO6: u32 = 4; pub const TUN_F_TSO_ECN: u32 = 8; pub const TUN_F_UFO: u32 = 16; +pub const TUN_F_USO4: u32 = 32; +pub const TUN_F_USO6: u32 = 64; pub const TUN_PKT_STRIP: u32 = 1; pub const TUN_FLT_ALLMULTI: u32 = 1; pub type __u8 = ::std::os::raw::c_uchar; @@ -144,102 +152,28 @@ pub struct sock_filter { pub jf: __u8, pub k: __u32, } -#[test] -fn bindgen_test_layout_sock_filter() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(sock_filter)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(sock_filter)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).code) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sock_filter), - "::", - stringify!(code) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).jt) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(sock_filter), - "::", - stringify!(jt) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).jf) as usize - ptr as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(sock_filter), - "::", - stringify!(jf) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).k) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(sock_filter), - "::", - stringify!(k) - ) - ); -} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of sock_filter"][::std::mem::size_of::() - 8usize]; + ["Alignment of sock_filter"][::std::mem::align_of::() - 4usize]; + ["Offset of field: sock_filter::code"][::std::mem::offset_of!(sock_filter, code) - 0usize]; + ["Offset of field: sock_filter::jt"][::std::mem::offset_of!(sock_filter, jt) - 2usize]; + ["Offset of field: sock_filter::jf"][::std::mem::offset_of!(sock_filter, jf) - 3usize]; + ["Offset of field: sock_filter::k"][::std::mem::offset_of!(sock_filter, k) - 4usize]; +}; #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq)] pub struct sock_fprog { pub len: ::std::os::raw::c_ushort, pub filter: *mut sock_filter, } -#[test] -fn bindgen_test_layout_sock_fprog() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(sock_fprog)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(sock_fprog)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sock_fprog), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).filter) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(sock_fprog), - "::", - stringify!(filter) - ) - ); -} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of sock_fprog"][::std::mem::size_of::() - 16usize]; + ["Alignment of sock_fprog"][::std::mem::align_of::() - 8usize]; + ["Offset of field: sock_fprog::len"][::std::mem::offset_of!(sock_fprog, len) - 0usize]; + ["Offset of field: sock_fprog::filter"][::std::mem::offset_of!(sock_fprog, filter) - 8usize]; +}; impl Default for sock_fprog { fn default() -> Self { let mut s = ::std::mem::MaybeUninit::::uninit(); diff --git a/src/vmm/src/devices/virtio/net/generated/iff.rs b/src/vmm/src/devices/virtio/net/generated/iff.rs new file mode 100644 index 00000000000..c805642a834 --- /dev/null +++ b/src/vmm/src/devices/virtio/net/generated/iff.rs @@ -0,0 +1,465 @@ +// 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 +)] + +pub const IFNAMSIZ: u32 = 16; +pub const IFALIASZ: u32 = 256; +pub const IF_GET_IFACE: u32 = 1; +pub const IF_GET_PROTO: u32 = 2; +pub const IF_IFACE_V35: u32 = 4096; +pub const IF_IFACE_V24: u32 = 4097; +pub const IF_IFACE_X21: u32 = 4098; +pub const IF_IFACE_T1: u32 = 4099; +pub const IF_IFACE_E1: u32 = 4100; +pub const IF_IFACE_SYNC_SERIAL: u32 = 4101; +pub const IF_IFACE_X21D: u32 = 4102; +pub const IF_PROTO_HDLC: u32 = 8192; +pub const IF_PROTO_PPP: u32 = 8193; +pub const IF_PROTO_CISCO: u32 = 8194; +pub const IF_PROTO_FR: u32 = 8195; +pub const IF_PROTO_FR_ADD_PVC: u32 = 8196; +pub const IF_PROTO_FR_DEL_PVC: u32 = 8197; +pub const IF_PROTO_X25: u32 = 8198; +pub const IF_PROTO_HDLC_ETH: u32 = 8199; +pub const IF_PROTO_FR_ADD_ETH_PVC: u32 = 8200; +pub const IF_PROTO_FR_DEL_ETH_PVC: u32 = 8201; +pub const IF_PROTO_FR_PVC: u32 = 8202; +pub const IF_PROTO_FR_ETH_PVC: u32 = 8203; +pub const IF_PROTO_RAW: u32 = 8204; +pub const IFHWADDRLEN: u32 = 6; +pub type sa_family_t = ::std::os::raw::c_ushort; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [::std::os::raw::c_char; 14usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of sockaddr"][::std::mem::size_of::() - 16usize]; + ["Alignment of sockaddr"][::std::mem::align_of::() - 2usize]; + ["Offset of field: sockaddr::sa_family"][::std::mem::offset_of!(sockaddr, sa_family) - 0usize]; + ["Offset of field: sockaddr::sa_data"][::std::mem::offset_of!(sockaddr, sa_data) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct sync_serial_settings { + pub clock_rate: ::std::os::raw::c_uint, + pub clock_type: ::std::os::raw::c_uint, + pub loopback: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of sync_serial_settings"][::std::mem::size_of::() - 12usize]; + ["Alignment of sync_serial_settings"][::std::mem::align_of::() - 4usize]; + ["Offset of field: sync_serial_settings::clock_rate"] + [::std::mem::offset_of!(sync_serial_settings, clock_rate) - 0usize]; + ["Offset of field: sync_serial_settings::clock_type"] + [::std::mem::offset_of!(sync_serial_settings, clock_type) - 4usize]; + ["Offset of field: sync_serial_settings::loopback"] + [::std::mem::offset_of!(sync_serial_settings, loopback) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct te1_settings { + pub clock_rate: ::std::os::raw::c_uint, + pub clock_type: ::std::os::raw::c_uint, + pub loopback: ::std::os::raw::c_ushort, + pub slot_map: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of te1_settings"][::std::mem::size_of::() - 16usize]; + ["Alignment of te1_settings"][::std::mem::align_of::() - 4usize]; + ["Offset of field: te1_settings::clock_rate"] + [::std::mem::offset_of!(te1_settings, clock_rate) - 0usize]; + ["Offset of field: te1_settings::clock_type"] + [::std::mem::offset_of!(te1_settings, clock_type) - 4usize]; + ["Offset of field: te1_settings::loopback"] + [::std::mem::offset_of!(te1_settings, loopback) - 8usize]; + ["Offset of field: te1_settings::slot_map"] + [::std::mem::offset_of!(te1_settings, slot_map) - 12usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct raw_hdlc_proto { + pub encoding: ::std::os::raw::c_ushort, + pub parity: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of raw_hdlc_proto"][::std::mem::size_of::() - 4usize]; + ["Alignment of raw_hdlc_proto"][::std::mem::align_of::() - 2usize]; + ["Offset of field: raw_hdlc_proto::encoding"] + [::std::mem::offset_of!(raw_hdlc_proto, encoding) - 0usize]; + ["Offset of field: raw_hdlc_proto::parity"] + [::std::mem::offset_of!(raw_hdlc_proto, parity) - 2usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct fr_proto { + pub t391: ::std::os::raw::c_uint, + pub t392: ::std::os::raw::c_uint, + pub n391: ::std::os::raw::c_uint, + pub n392: ::std::os::raw::c_uint, + pub n393: ::std::os::raw::c_uint, + pub lmi: ::std::os::raw::c_ushort, + pub dce: ::std::os::raw::c_ushort, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of fr_proto"][::std::mem::size_of::() - 24usize]; + ["Alignment of fr_proto"][::std::mem::align_of::() - 4usize]; + ["Offset of field: fr_proto::t391"][::std::mem::offset_of!(fr_proto, t391) - 0usize]; + ["Offset of field: fr_proto::t392"][::std::mem::offset_of!(fr_proto, t392) - 4usize]; + ["Offset of field: fr_proto::n391"][::std::mem::offset_of!(fr_proto, n391) - 8usize]; + ["Offset of field: fr_proto::n392"][::std::mem::offset_of!(fr_proto, n392) - 12usize]; + ["Offset of field: fr_proto::n393"][::std::mem::offset_of!(fr_proto, n393) - 16usize]; + ["Offset of field: fr_proto::lmi"][::std::mem::offset_of!(fr_proto, lmi) - 20usize]; + ["Offset of field: fr_proto::dce"][::std::mem::offset_of!(fr_proto, dce) - 22usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct fr_proto_pvc { + pub dlci: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of fr_proto_pvc"][::std::mem::size_of::() - 4usize]; + ["Alignment of fr_proto_pvc"][::std::mem::align_of::() - 4usize]; + ["Offset of field: fr_proto_pvc::dlci"][::std::mem::offset_of!(fr_proto_pvc, dlci) - 0usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct fr_proto_pvc_info { + pub dlci: ::std::os::raw::c_uint, + pub master: [::std::os::raw::c_char; 16usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of fr_proto_pvc_info"][::std::mem::size_of::() - 20usize]; + ["Alignment of fr_proto_pvc_info"][::std::mem::align_of::() - 4usize]; + ["Offset of field: fr_proto_pvc_info::dlci"] + [::std::mem::offset_of!(fr_proto_pvc_info, dlci) - 0usize]; + ["Offset of field: fr_proto_pvc_info::master"] + [::std::mem::offset_of!(fr_proto_pvc_info, master) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct cisco_proto { + pub interval: ::std::os::raw::c_uint, + pub timeout: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of cisco_proto"][::std::mem::size_of::() - 8usize]; + ["Alignment of cisco_proto"][::std::mem::align_of::() - 4usize]; + ["Offset of field: cisco_proto::interval"] + [::std::mem::offset_of!(cisco_proto, interval) - 0usize]; + ["Offset of field: cisco_proto::timeout"] + [::std::mem::offset_of!(cisco_proto, timeout) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct x25_hdlc_proto { + pub dce: ::std::os::raw::c_ushort, + pub modulo: ::std::os::raw::c_uint, + pub window: ::std::os::raw::c_uint, + pub t1: ::std::os::raw::c_uint, + pub t2: ::std::os::raw::c_uint, + pub n2: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of x25_hdlc_proto"][::std::mem::size_of::() - 24usize]; + ["Alignment of x25_hdlc_proto"][::std::mem::align_of::() - 4usize]; + ["Offset of field: x25_hdlc_proto::dce"][::std::mem::offset_of!(x25_hdlc_proto, dce) - 0usize]; + ["Offset of field: x25_hdlc_proto::modulo"] + [::std::mem::offset_of!(x25_hdlc_proto, modulo) - 4usize]; + ["Offset of field: x25_hdlc_proto::window"] + [::std::mem::offset_of!(x25_hdlc_proto, window) - 8usize]; + ["Offset of field: x25_hdlc_proto::t1"][::std::mem::offset_of!(x25_hdlc_proto, t1) - 12usize]; + ["Offset of field: x25_hdlc_proto::t2"][::std::mem::offset_of!(x25_hdlc_proto, t2) - 16usize]; + ["Offset of field: x25_hdlc_proto::n2"][::std::mem::offset_of!(x25_hdlc_proto, n2) - 20usize]; +}; +pub const net_device_flags_IFF_UP: net_device_flags = 1; +pub const net_device_flags_IFF_BROADCAST: net_device_flags = 2; +pub const net_device_flags_IFF_DEBUG: net_device_flags = 4; +pub const net_device_flags_IFF_LOOPBACK: net_device_flags = 8; +pub const net_device_flags_IFF_POINTOPOINT: net_device_flags = 16; +pub const net_device_flags_IFF_NOTRAILERS: net_device_flags = 32; +pub const net_device_flags_IFF_RUNNING: net_device_flags = 64; +pub const net_device_flags_IFF_NOARP: net_device_flags = 128; +pub const net_device_flags_IFF_PROMISC: net_device_flags = 256; +pub const net_device_flags_IFF_ALLMULTI: net_device_flags = 512; +pub const net_device_flags_IFF_MASTER: net_device_flags = 1024; +pub const net_device_flags_IFF_SLAVE: net_device_flags = 2048; +pub const net_device_flags_IFF_MULTICAST: net_device_flags = 4096; +pub const net_device_flags_IFF_PORTSEL: net_device_flags = 8192; +pub const net_device_flags_IFF_AUTOMEDIA: net_device_flags = 16384; +pub const net_device_flags_IFF_DYNAMIC: net_device_flags = 32768; +pub const net_device_flags_IFF_LOWER_UP: net_device_flags = 65536; +pub const net_device_flags_IFF_DORMANT: net_device_flags = 131072; +pub const net_device_flags_IFF_ECHO: net_device_flags = 262144; +pub type net_device_flags = ::std::os::raw::c_uint; +pub const IF_OPER_UNKNOWN: _bindgen_ty_4 = 0; +pub const IF_OPER_NOTPRESENT: _bindgen_ty_4 = 1; +pub const IF_OPER_DOWN: _bindgen_ty_4 = 2; +pub const IF_OPER_LOWERLAYERDOWN: _bindgen_ty_4 = 3; +pub const IF_OPER_TESTING: _bindgen_ty_4 = 4; +pub const IF_OPER_DORMANT: _bindgen_ty_4 = 5; +pub const IF_OPER_UP: _bindgen_ty_4 = 6; +pub type _bindgen_ty_4 = ::std::os::raw::c_uint; +pub const IF_LINK_MODE_DEFAULT: _bindgen_ty_5 = 0; +pub const IF_LINK_MODE_DORMANT: _bindgen_ty_5 = 1; +pub const IF_LINK_MODE_TESTING: _bindgen_ty_5 = 2; +pub type _bindgen_ty_5 = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct ifmap { + pub mem_start: ::std::os::raw::c_ulong, + pub mem_end: ::std::os::raw::c_ulong, + pub base_addr: ::std::os::raw::c_ushort, + pub irq: ::std::os::raw::c_uchar, + pub dma: ::std::os::raw::c_uchar, + pub port: ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ifmap"][::std::mem::size_of::() - 24usize]; + ["Alignment of ifmap"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ifmap::mem_start"][::std::mem::offset_of!(ifmap, mem_start) - 0usize]; + ["Offset of field: ifmap::mem_end"][::std::mem::offset_of!(ifmap, mem_end) - 8usize]; + ["Offset of field: ifmap::base_addr"][::std::mem::offset_of!(ifmap, base_addr) - 16usize]; + ["Offset of field: ifmap::irq"][::std::mem::offset_of!(ifmap, irq) - 18usize]; + ["Offset of field: ifmap::dma"][::std::mem::offset_of!(ifmap, dma) - 19usize]; + ["Offset of field: ifmap::port"][::std::mem::offset_of!(ifmap, port) - 20usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct if_settings { + pub type_: ::std::os::raw::c_uint, + pub size: ::std::os::raw::c_uint, + pub ifs_ifsu: if_settings__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union if_settings__bindgen_ty_1 { + pub raw_hdlc: *mut raw_hdlc_proto, + pub cisco: *mut cisco_proto, + pub fr: *mut fr_proto, + pub fr_pvc: *mut fr_proto_pvc, + pub fr_pvc_info: *mut fr_proto_pvc_info, + pub x25: *mut x25_hdlc_proto, + pub sync: *mut sync_serial_settings, + pub te1: *mut te1_settings, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of if_settings__bindgen_ty_1"] + [::std::mem::size_of::() - 8usize]; + ["Alignment of if_settings__bindgen_ty_1"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: if_settings__bindgen_ty_1::raw_hdlc"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, raw_hdlc) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::cisco"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, cisco) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::fr"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, fr) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::fr_pvc"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, fr_pvc) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::fr_pvc_info"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, fr_pvc_info) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::x25"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, x25) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::sync"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, sync) - 0usize]; + ["Offset of field: if_settings__bindgen_ty_1::te1"] + [::std::mem::offset_of!(if_settings__bindgen_ty_1, te1) - 0usize]; +}; +impl Default for if_settings__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 if_settings"][::std::mem::size_of::() - 16usize]; + ["Alignment of if_settings"][::std::mem::align_of::() - 8usize]; + ["Offset of field: if_settings::type_"][::std::mem::offset_of!(if_settings, type_) - 0usize]; + ["Offset of field: if_settings::size"][::std::mem::offset_of!(if_settings, size) - 4usize]; + ["Offset of field: if_settings::ifs_ifsu"] + [::std::mem::offset_of!(if_settings, ifs_ifsu) - 8usize]; +}; +impl Default for if_settings { + 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(Copy, Clone)] +pub struct ifreq { + pub ifr_ifrn: ifreq__bindgen_ty_1, + pub ifr_ifru: ifreq__bindgen_ty_2, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union ifreq__bindgen_ty_1 { + pub ifrn_name: [::std::os::raw::c_uchar; 16usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ifreq__bindgen_ty_1"][::std::mem::size_of::() - 16usize]; + ["Alignment of ifreq__bindgen_ty_1"][::std::mem::align_of::() - 1usize]; + ["Offset of field: ifreq__bindgen_ty_1::ifrn_name"] + [::std::mem::offset_of!(ifreq__bindgen_ty_1, ifrn_name) - 0usize]; +}; +impl Default for ifreq__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() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union ifreq__bindgen_ty_2 { + pub ifru_addr: sockaddr, + pub ifru_dstaddr: sockaddr, + pub ifru_broadaddr: sockaddr, + pub ifru_netmask: sockaddr, + pub ifru_hwaddr: sockaddr, + pub ifru_flags: ::std::os::raw::c_short, + pub ifru_ivalue: ::std::os::raw::c_int, + pub ifru_mtu: ::std::os::raw::c_int, + pub ifru_map: ifmap, + pub ifru_slave: [::std::os::raw::c_char; 16usize], + pub ifru_newname: [::std::os::raw::c_char; 16usize], + pub ifru_data: *mut ::std::os::raw::c_void, + pub ifru_settings: if_settings, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ifreq__bindgen_ty_2"][::std::mem::size_of::() - 24usize]; + ["Alignment of ifreq__bindgen_ty_2"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_addr"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_addr) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_dstaddr"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_dstaddr) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_broadaddr"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_broadaddr) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_netmask"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_netmask) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_hwaddr"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_hwaddr) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_flags"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_flags) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_ivalue"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_ivalue) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_mtu"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_mtu) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_map"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_map) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_slave"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_slave) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_newname"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_newname) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_data"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_data) - 0usize]; + ["Offset of field: ifreq__bindgen_ty_2::ifru_settings"] + [::std::mem::offset_of!(ifreq__bindgen_ty_2, ifru_settings) - 0usize]; +}; +impl Default for ifreq__bindgen_ty_2 { + 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 ifreq"][::std::mem::size_of::() - 40usize]; + ["Alignment of ifreq"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ifreq::ifr_ifrn"][::std::mem::offset_of!(ifreq, ifr_ifrn) - 0usize]; + ["Offset of field: ifreq::ifr_ifru"][::std::mem::offset_of!(ifreq, ifr_ifru) - 16usize]; +}; +impl Default for ifreq { + 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(Copy, Clone)] +pub struct ifconf { + pub ifc_len: ::std::os::raw::c_int, + pub ifc_ifcu: ifconf__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union ifconf__bindgen_ty_1 { + pub ifcu_buf: *mut ::std::os::raw::c_char, + pub ifcu_req: *mut ifreq, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of ifconf__bindgen_ty_1"][::std::mem::size_of::() - 8usize]; + ["Alignment of ifconf__bindgen_ty_1"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ifconf__bindgen_ty_1::ifcu_buf"] + [::std::mem::offset_of!(ifconf__bindgen_ty_1, ifcu_buf) - 0usize]; + ["Offset of field: ifconf__bindgen_ty_1::ifcu_req"] + [::std::mem::offset_of!(ifconf__bindgen_ty_1, ifcu_req) - 0usize]; +}; +impl Default for ifconf__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 ifconf"][::std::mem::size_of::() - 16usize]; + ["Alignment of ifconf"][::std::mem::align_of::() - 8usize]; + ["Offset of field: ifconf::ifc_len"][::std::mem::offset_of!(ifconf, ifc_len) - 0usize]; + ["Offset of field: ifconf::ifc_ifcu"][::std::mem::offset_of!(ifconf, ifc_ifcu) - 8usize]; +}; +impl Default for ifconf { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} diff --git a/src/vmm/src/devices/virtio/net/gen/mod.rs b/src/vmm/src/devices/virtio/net/generated/mod.rs similarity index 100% rename from src/vmm/src/devices/virtio/net/gen/mod.rs rename to src/vmm/src/devices/virtio/net/generated/mod.rs diff --git a/src/vmm/src/devices/virtio/net/gen/sockios.rs b/src/vmm/src/devices/virtio/net/generated/sockios.rs similarity index 96% rename from src/vmm/src/devices/virtio/net/gen/sockios.rs rename to src/vmm/src/devices/virtio/net/generated/sockios.rs index d1ffd6af27c..8973c1cf877 100644 --- a/src/vmm/src/devices/virtio/net/gen/sockios.rs +++ b/src/vmm/src/devices/virtio/net/generated/sockios.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // automatically generated by tools/bindgen.sh @@ -11,7 +11,8 @@ clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, missing_debug_implementations, - clippy::tests_outside_test_module + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn )] pub const __BITS_PER_LONG: u32 = 64; diff --git a/src/vmm/src/devices/virtio/net/mod.rs b/src/vmm/src/devices/virtio/net/mod.rs index 4bc5b896601..31b0f8a178c 100644 --- a/src/vmm/src/devices/virtio/net/mod.rs +++ b/src/vmm/src/devices/virtio/net/mod.rs @@ -24,7 +24,7 @@ pub mod persist; mod tap; pub mod test_utils; -mod gen; +mod generated; pub use tap::{Tap, TapError}; use vm_memory::VolatileMemoryError; diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 776b5ba960e..7b3b7b01142 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -15,7 +15,7 @@ use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val}; use vmm_sys_util::{ioctl_ioc_nr, ioctl_iow_nr}; use crate::devices::virtio::iovec::IoVecBuffer; -use crate::devices::virtio::net::gen; +use crate::devices::virtio::net::generated; // As defined in the Linux UAPI: // https://elixir.bootlin.com/linux/v4.17/source/include/uapi/linux/if.h#L33 @@ -71,7 +71,7 @@ fn build_terminated_if_name(if_name: &str) -> Result<[u8; IFACE_NAME_MAX_LEN], T } #[derive(Copy, Clone)] -pub struct IfReqBuilder(gen::ifreq); +pub struct IfReqBuilder(generated::ifreq); impl fmt::Debug for IfReqBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -102,7 +102,7 @@ impl IfReqBuilder { mut self, socket: &F, ioctl: u64, - ) -> std::io::Result { + ) -> std::io::Result { // SAFETY: ioctl is safe. Called with a valid socket fd, and we check the return. if unsafe { ioctl_with_mut_ref(socket, ioctl, &mut self.0) } < 0 { return Err(IoError::last_os_error()); @@ -136,7 +136,7 @@ impl Tap { let terminated_if_name = build_terminated_if_name(if_name)?; let ifreq = IfReqBuilder::new() .if_name(&terminated_if_name) - .flags(i16::try_from(gen::IFF_TAP | gen::IFF_NO_PI | gen::IFF_VNET_HDR).unwrap()) + .flags(i16::try_from(generated::IFF_TAP | generated::IFF_NO_PI | generated::IFF_VNET_HDR).unwrap()) .execute(&tuntap, TUNSETIFF()) .map_err(|io_error| TapError::IfreqExecuteError(io_error, if_name.to_owned()))?; @@ -219,7 +219,7 @@ pub mod tests { use std::os::unix::ffi::OsStrExt; use super::*; - use crate::devices::virtio::net::gen; + use crate::devices::virtio::net::generated; use crate::devices::virtio::net::test_utils::{enable, if_index, TapTrafficSimulator}; // Redefine `IoVecBufferMut` with specific length. Otherwise @@ -235,7 +235,7 @@ pub mod tests { fn test_tap_name() { // Sanity check that the assumed max iface name length is correct. assert_eq!(IFACE_NAME_MAX_LEN, unsafe { - gen::ifreq__bindgen_ty_1::default().ifrn_name.len() + generated::ifreq__bindgen_ty_1::default().ifrn_name.len() }); // Empty name - The tap should be named "tap0" by default @@ -292,8 +292,8 @@ pub mod tests { let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&tap)); let mut fragment1 = vmm_sys_util::rand::rand_bytes(PAYLOAD_SIZE); - fragment1.as_mut_slice()[..gen::ETH_HLEN as usize] - .copy_from_slice(&[0; gen::ETH_HLEN as usize]); + fragment1.as_mut_slice()[..generated::ETH_HLEN as usize] + .copy_from_slice(&[0; generated::ETH_HLEN as usize]); let fragment2 = vmm_sys_util::rand::rand_bytes(PAYLOAD_SIZE); let fragment3 = vmm_sys_util::rand::rand_bytes(PAYLOAD_SIZE); diff --git a/src/vmm/src/devices/virtio/net/test_utils.rs b/src/vmm/src/devices/virtio/net/test_utils.rs index ffe7bbc7279..167f4f909b8 100644 --- a/src/vmm/src/devices/virtio/net/test_utils.rs +++ b/src/vmm/src/devices/virtio/net/test_utils.rs @@ -211,7 +211,7 @@ pub fn if_index(tap: &Tap) -> i32 { let sock = create_socket(); let ifreq = IfReqBuilder::new() .if_name(&tap.if_name) - .execute(&sock, c_ulong::from(super::gen::sockios::SIOCGIFINDEX)) + .execute(&sock, c_ulong::from(super::generated::sockios::SIOCGIFINDEX)) .unwrap(); // SAFETY: Using this union variant is safe since `SIOCGIFINDEX` returns an integer. @@ -234,13 +234,13 @@ pub fn enable(tap: &Tap) { IfReqBuilder::new() .if_name(&tap.if_name) .flags( - (crate::devices::virtio::net::gen::net_device_flags_IFF_UP - | crate::devices::virtio::net::gen::net_device_flags_IFF_RUNNING - | crate::devices::virtio::net::gen::net_device_flags_IFF_NOARP) + (crate::devices::virtio::net::generated::net_device_flags_IFF_UP + | crate::devices::virtio::net::generated::net_device_flags_IFF_RUNNING + | crate::devices::virtio::net::generated::net_device_flags_IFF_NOARP) .try_into() .unwrap(), ) - .execute(&sock, c_ulong::from(super::gen::sockios::SIOCSIFFLAGS)) + .execute(&sock, c_ulong::from(super::generated::sockios::SIOCSIFFLAGS)) .unwrap(); } @@ -307,7 +307,7 @@ pub mod test { use crate::check_metric_after_block; use crate::devices::virtio::device::{IrqType, VirtioDevice}; use crate::devices::virtio::net::device::vnet_hdr_len; - use crate::devices::virtio::net::gen::ETH_HLEN; + use crate::devices::virtio::net::generated::ETH_HLEN; use crate::devices::virtio::net::test_utils::{ assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue, }; diff --git a/src/vmm/src/devices/virtio/persist.rs b/src/vmm/src/devices/virtio/persist.rs index d0938797f65..cd7d1245dd9 100644 --- a/src/vmm/src/devices/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/persist.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use super::queue::QueueError; use crate::devices::virtio::device::VirtioDevice; -use crate::devices::virtio::gen::virtio_ring::VIRTIO_RING_F_EVENT_IDX; +use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::mmio::MmioTransport; use crate::devices::virtio::queue::Queue; use crate::snapshot::Persist; diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs index dca25999f3e..a6e9055e0a0 100644 --- a/src/vmm/src/devices/virtio/rng/device.rs +++ b/src/vmm/src/devices/virtio/rng/device.rs @@ -12,7 +12,7 @@ use vmm_sys_util::eventfd::EventFd; use super::metrics::METRICS; use super::{RNG_NUM_QUEUES, RNG_QUEUE}; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::gen::virtio_rng::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_rng::VIRTIO_F_VERSION_1; use crate::devices::virtio::iov_deque::IovDequeError; use crate::devices::virtio::iovec::IoVecBufferMut; use crate::devices::virtio::queue::{Queue, FIRECRACKER_MAX_QUEUE_SIZE}; diff --git a/src/vmm/src/io_uring/gen.rs b/src/vmm/src/io_uring/gen.rs deleted file mode 100644 index c18a3aa36ec..00000000000 --- a/src/vmm/src/io_uring/gen.rs +++ /dev/null @@ -1,1712 +0,0 @@ -// Copyright 2024 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 -)] - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); -impl __IncompleteArrayField { - #[inline] - pub const fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData, []) - } - #[inline] - pub fn as_ptr(&self) -> *const T { - self as *const _ as *const T - } - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - self as *mut _ as *mut T - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -pub const IORING_SETUP_IOPOLL: u32 = 1; -pub const IORING_SETUP_SQPOLL: u32 = 2; -pub const IORING_SETUP_SQ_AFF: u32 = 4; -pub const IORING_SETUP_CQSIZE: u32 = 8; -pub const IORING_SETUP_CLAMP: u32 = 16; -pub const IORING_SETUP_ATTACH_WQ: u32 = 32; -pub const IORING_SETUP_R_DISABLED: u32 = 64; -pub const IORING_FSYNC_DATASYNC: u32 = 1; -pub const IORING_TIMEOUT_ABS: u32 = 1; -pub const IORING_TIMEOUT_UPDATE: u32 = 2; -pub const IORING_TIMEOUT_BOOTTIME: u32 = 4; -pub const IORING_TIMEOUT_REALTIME: u32 = 8; -pub const IORING_LINK_TIMEOUT_UPDATE: u32 = 16; -pub const IORING_TIMEOUT_CLOCK_MASK: u32 = 12; -pub const IORING_TIMEOUT_UPDATE_MASK: u32 = 18; -pub const IORING_POLL_ADD_MULTI: u32 = 1; -pub const IORING_POLL_UPDATE_EVENTS: u32 = 2; -pub const IORING_POLL_UPDATE_USER_DATA: u32 = 4; -pub const IORING_CQE_F_BUFFER: u32 = 1; -pub const IORING_CQE_F_MORE: u32 = 2; -pub const IORING_OFF_SQ_RING: u32 = 0; -pub const IORING_OFF_CQ_RING: u32 = 134217728; -pub const IORING_OFF_SQES: u32 = 268435456; -pub const IORING_SQ_NEED_WAKEUP: u32 = 1; -pub const IORING_SQ_CQ_OVERFLOW: u32 = 2; -pub const IORING_CQ_EVENTFD_DISABLED: u32 = 1; -pub const IORING_ENTER_GETEVENTS: u32 = 1; -pub const IORING_ENTER_SQ_WAKEUP: u32 = 2; -pub const IORING_ENTER_SQ_WAIT: u32 = 4; -pub const IORING_ENTER_EXT_ARG: u32 = 8; -pub const IORING_FEAT_SINGLE_MMAP: u32 = 1; -pub const IORING_FEAT_NODROP: u32 = 2; -pub const IORING_FEAT_SUBMIT_STABLE: u32 = 4; -pub const IORING_FEAT_RW_CUR_POS: u32 = 8; -pub const IORING_FEAT_CUR_PERSONALITY: u32 = 16; -pub const IORING_FEAT_FAST_POLL: u32 = 32; -pub const IORING_FEAT_POLL_32BITS: u32 = 64; -pub const IORING_FEAT_SQPOLL_NONFIXED: u32 = 128; -pub const IORING_FEAT_EXT_ARG: u32 = 256; -pub const IORING_FEAT_NATIVE_WORKERS: u32 = 512; -pub const IORING_FEAT_RSRC_TAGS: u32 = 1024; -pub const IORING_REGISTER_FILES_SKIP: i32 = -2; -pub const IO_URING_OP_SUPPORTED: u32 = 1; -pub type __u8 = ::std::os::raw::c_uchar; -pub type __u16 = ::std::os::raw::c_ushort; -pub type __s32 = ::std::os::raw::c_int; -pub type __u32 = ::std::os::raw::c_uint; -pub type __u64 = ::std::os::raw::c_ulonglong; -pub type __kernel_rwf_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct io_uring_sqe { - pub opcode: __u8, - pub flags: __u8, - pub ioprio: __u16, - pub fd: __s32, - pub __bindgen_anon_1: io_uring_sqe__bindgen_ty_1, - pub __bindgen_anon_2: io_uring_sqe__bindgen_ty_2, - pub len: __u32, - pub __bindgen_anon_3: io_uring_sqe__bindgen_ty_3, - pub user_data: __u64, - pub __bindgen_anon_4: io_uring_sqe__bindgen_ty_4, - pub personality: __u16, - pub __bindgen_anon_5: io_uring_sqe__bindgen_ty_5, - pub __pad2: [__u64; 2usize], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union io_uring_sqe__bindgen_ty_1 { - pub off: __u64, - pub addr2: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_sqe__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(io_uring_sqe__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_sqe__bindgen_ty_1)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).off) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_1), - "::", - stringify!(off) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).addr2) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_1), - "::", - stringify!(addr2) - ) - ); -} -impl Default for io_uring_sqe__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() - } - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union io_uring_sqe__bindgen_ty_2 { - pub addr: __u64, - pub splice_off_in: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_sqe__bindgen_ty_2() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(io_uring_sqe__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_sqe__bindgen_ty_2)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_2), - "::", - stringify!(addr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).splice_off_in) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_2), - "::", - stringify!(splice_off_in) - ) - ); -} -impl Default for io_uring_sqe__bindgen_ty_2 { - 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(Copy, Clone)] -pub union io_uring_sqe__bindgen_ty_3 { - pub rw_flags: __kernel_rwf_t, - pub fsync_flags: __u32, - pub poll_events: __u16, - pub poll32_events: __u32, - pub sync_range_flags: __u32, - pub msg_flags: __u32, - pub timeout_flags: __u32, - pub accept_flags: __u32, - pub cancel_flags: __u32, - pub open_flags: __u32, - pub statx_flags: __u32, - pub fadvise_advice: __u32, - pub splice_flags: __u32, - pub rename_flags: __u32, - pub unlink_flags: __u32, - pub hardlink_flags: __u32, -} -#[test] -fn bindgen_test_layout_io_uring_sqe__bindgen_ty_3() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(io_uring_sqe__bindgen_ty_3)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(io_uring_sqe__bindgen_ty_3)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rw_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(rw_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fsync_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(fsync_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).poll_events) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(poll_events) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).poll32_events) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(poll32_events) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sync_range_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(sync_range_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msg_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(msg_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).timeout_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(timeout_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).accept_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(accept_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cancel_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(cancel_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).open_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(open_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).statx_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(statx_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fadvise_advice) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(fadvise_advice) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).splice_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(splice_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rename_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(rename_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).unlink_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(unlink_flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).hardlink_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_3), - "::", - stringify!(hardlink_flags) - ) - ); -} -impl Default for io_uring_sqe__bindgen_ty_3 { - 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, packed)] -#[derive(Copy, Clone)] -pub union io_uring_sqe__bindgen_ty_4 { - pub buf_index: __u16, - pub buf_group: __u16, -} -#[test] -fn bindgen_test_layout_io_uring_sqe__bindgen_ty_4() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 2usize, - concat!("Size of: ", stringify!(io_uring_sqe__bindgen_ty_4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(io_uring_sqe__bindgen_ty_4)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).buf_index) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_4), - "::", - stringify!(buf_index) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).buf_group) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_4), - "::", - stringify!(buf_group) - ) - ); -} -impl Default for io_uring_sqe__bindgen_ty_4 { - 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(Copy, Clone)] -pub union io_uring_sqe__bindgen_ty_5 { - pub splice_fd_in: __s32, - pub file_index: __u32, -} -#[test] -fn bindgen_test_layout_io_uring_sqe__bindgen_ty_5() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(io_uring_sqe__bindgen_ty_5)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(io_uring_sqe__bindgen_ty_5)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).splice_fd_in) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_5), - "::", - stringify!(splice_fd_in) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).file_index) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe__bindgen_ty_5), - "::", - stringify!(file_index) - ) - ); -} -impl Default for io_uring_sqe__bindgen_ty_5 { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} -#[test] -fn bindgen_test_layout_io_uring_sqe() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 64usize, - concat!("Size of: ", stringify!(io_uring_sqe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_sqe)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).opcode) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(opcode) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ioprio) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(ioprio) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fd) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(fd) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).user_data) as usize - ptr as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(user_data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).personality) as usize - ptr as usize }, - 42usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(personality) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).__pad2) as usize - ptr as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(io_uring_sqe), - "::", - stringify!(__pad2) - ) - ); -} -impl Default for io_uring_sqe { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} -pub const IOSQE_FIXED_FILE_BIT: _bindgen_ty_1 = 0; -pub const IOSQE_IO_DRAIN_BIT: _bindgen_ty_1 = 1; -pub const IOSQE_IO_LINK_BIT: _bindgen_ty_1 = 2; -pub const IOSQE_IO_HARDLINK_BIT: _bindgen_ty_1 = 3; -pub const IOSQE_ASYNC_BIT: _bindgen_ty_1 = 4; -pub const IOSQE_BUFFER_SELECT_BIT: _bindgen_ty_1 = 5; -pub type _bindgen_ty_1 = ::std::os::raw::c_uint; -pub const IORING_OP_NOP: _bindgen_ty_2 = 0; -pub const IORING_OP_READV: _bindgen_ty_2 = 1; -pub const IORING_OP_WRITEV: _bindgen_ty_2 = 2; -pub const IORING_OP_FSYNC: _bindgen_ty_2 = 3; -pub const IORING_OP_READ_FIXED: _bindgen_ty_2 = 4; -pub const IORING_OP_WRITE_FIXED: _bindgen_ty_2 = 5; -pub const IORING_OP_POLL_ADD: _bindgen_ty_2 = 6; -pub const IORING_OP_POLL_REMOVE: _bindgen_ty_2 = 7; -pub const IORING_OP_SYNC_FILE_RANGE: _bindgen_ty_2 = 8; -pub const IORING_OP_SENDMSG: _bindgen_ty_2 = 9; -pub const IORING_OP_RECVMSG: _bindgen_ty_2 = 10; -pub const IORING_OP_TIMEOUT: _bindgen_ty_2 = 11; -pub const IORING_OP_TIMEOUT_REMOVE: _bindgen_ty_2 = 12; -pub const IORING_OP_ACCEPT: _bindgen_ty_2 = 13; -pub const IORING_OP_ASYNC_CANCEL: _bindgen_ty_2 = 14; -pub const IORING_OP_LINK_TIMEOUT: _bindgen_ty_2 = 15; -pub const IORING_OP_CONNECT: _bindgen_ty_2 = 16; -pub const IORING_OP_FALLOCATE: _bindgen_ty_2 = 17; -pub const IORING_OP_OPENAT: _bindgen_ty_2 = 18; -pub const IORING_OP_CLOSE: _bindgen_ty_2 = 19; -pub const IORING_OP_FILES_UPDATE: _bindgen_ty_2 = 20; -pub const IORING_OP_STATX: _bindgen_ty_2 = 21; -pub const IORING_OP_READ: _bindgen_ty_2 = 22; -pub const IORING_OP_WRITE: _bindgen_ty_2 = 23; -pub const IORING_OP_FADVISE: _bindgen_ty_2 = 24; -pub const IORING_OP_MADVISE: _bindgen_ty_2 = 25; -pub const IORING_OP_SEND: _bindgen_ty_2 = 26; -pub const IORING_OP_RECV: _bindgen_ty_2 = 27; -pub const IORING_OP_OPENAT2: _bindgen_ty_2 = 28; -pub const IORING_OP_EPOLL_CTL: _bindgen_ty_2 = 29; -pub const IORING_OP_SPLICE: _bindgen_ty_2 = 30; -pub const IORING_OP_PROVIDE_BUFFERS: _bindgen_ty_2 = 31; -pub const IORING_OP_REMOVE_BUFFERS: _bindgen_ty_2 = 32; -pub const IORING_OP_TEE: _bindgen_ty_2 = 33; -pub const IORING_OP_SHUTDOWN: _bindgen_ty_2 = 34; -pub const IORING_OP_RENAMEAT: _bindgen_ty_2 = 35; -pub const IORING_OP_UNLINKAT: _bindgen_ty_2 = 36; -pub const IORING_OP_LAST: _bindgen_ty_2 = 37; -pub type _bindgen_ty_2 = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_cqe { - pub user_data: __u64, - pub res: __s32, - pub flags: __u32, -} -#[test] -fn bindgen_test_layout_io_uring_cqe() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(io_uring_cqe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_cqe)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).user_data) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_cqe), - "::", - stringify!(user_data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).res) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_cqe), - "::", - stringify!(res) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(io_uring_cqe), - "::", - stringify!(flags) - ) - ); -} -pub const IORING_CQE_BUFFER_SHIFT: _bindgen_ty_3 = 16; -pub type _bindgen_ty_3 = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_sqring_offsets { - pub head: __u32, - pub tail: __u32, - pub ring_mask: __u32, - pub ring_entries: __u32, - pub flags: __u32, - pub dropped: __u32, - pub array: __u32, - pub resv1: __u32, - pub resv2: __u64, -} -#[test] -fn bindgen_test_layout_io_sqring_offsets() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(io_sqring_offsets)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_sqring_offsets)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).head) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(head) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tail) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(tail) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ring_mask) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(ring_mask) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ring_entries) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(ring_entries) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).dropped) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(dropped) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).array) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(array) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv1) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(resv1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(io_sqring_offsets), - "::", - stringify!(resv2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_cqring_offsets { - pub head: __u32, - pub tail: __u32, - pub ring_mask: __u32, - pub ring_entries: __u32, - pub overflow: __u32, - pub cqes: __u32, - pub flags: __u32, - pub resv1: __u32, - pub resv2: __u64, -} -#[test] -fn bindgen_test_layout_io_cqring_offsets() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(io_cqring_offsets)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_cqring_offsets)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).head) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(head) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tail) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(tail) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ring_mask) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(ring_mask) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ring_entries) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(ring_entries) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).overflow) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(overflow) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cqes) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(cqes) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv1) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(resv1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(io_cqring_offsets), - "::", - stringify!(resv2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_params { - pub sq_entries: __u32, - pub cq_entries: __u32, - pub flags: __u32, - pub sq_thread_cpu: __u32, - pub sq_thread_idle: __u32, - pub features: __u32, - pub wq_fd: __u32, - pub resv: [__u32; 3usize], - pub sq_off: io_sqring_offsets, - pub cq_off: io_cqring_offsets, -} -#[test] -fn bindgen_test_layout_io_uring_params() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 120usize, - concat!("Size of: ", stringify!(io_uring_params)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_params)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sq_entries) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(sq_entries) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cq_entries) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(cq_entries) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sq_thread_cpu) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(sq_thread_cpu) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sq_thread_idle) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(sq_thread_idle) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).features) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(features) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).wq_fd) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(wq_fd) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sq_off) as usize - ptr as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(sq_off) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cq_off) as usize - ptr as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(io_uring_params), - "::", - stringify!(cq_off) - ) - ); -} -pub const IORING_REGISTER_BUFFERS: _bindgen_ty_4 = 0; -pub const IORING_UNREGISTER_BUFFERS: _bindgen_ty_4 = 1; -pub const IORING_REGISTER_FILES: _bindgen_ty_4 = 2; -pub const IORING_UNREGISTER_FILES: _bindgen_ty_4 = 3; -pub const IORING_REGISTER_EVENTFD: _bindgen_ty_4 = 4; -pub const IORING_UNREGISTER_EVENTFD: _bindgen_ty_4 = 5; -pub const IORING_REGISTER_FILES_UPDATE: _bindgen_ty_4 = 6; -pub const IORING_REGISTER_EVENTFD_ASYNC: _bindgen_ty_4 = 7; -pub const IORING_REGISTER_PROBE: _bindgen_ty_4 = 8; -pub const IORING_REGISTER_PERSONALITY: _bindgen_ty_4 = 9; -pub const IORING_UNREGISTER_PERSONALITY: _bindgen_ty_4 = 10; -pub const IORING_REGISTER_RESTRICTIONS: _bindgen_ty_4 = 11; -pub const IORING_REGISTER_ENABLE_RINGS: _bindgen_ty_4 = 12; -pub const IORING_REGISTER_FILES2: _bindgen_ty_4 = 13; -pub const IORING_REGISTER_FILES_UPDATE2: _bindgen_ty_4 = 14; -pub const IORING_REGISTER_BUFFERS2: _bindgen_ty_4 = 15; -pub const IORING_REGISTER_BUFFERS_UPDATE: _bindgen_ty_4 = 16; -pub const IORING_REGISTER_IOWQ_AFF: _bindgen_ty_4 = 17; -pub const IORING_UNREGISTER_IOWQ_AFF: _bindgen_ty_4 = 18; -pub const IORING_REGISTER_IOWQ_MAX_WORKERS: _bindgen_ty_4 = 19; -pub const IORING_REGISTER_LAST: _bindgen_ty_4 = 20; -pub type _bindgen_ty_4 = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_files_update { - pub offset: __u32, - pub resv: __u32, - pub fds: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_files_update() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(io_uring_files_update)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_files_update)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_files_update), - "::", - stringify!(offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_files_update), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).fds) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_files_update), - "::", - stringify!(fds) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_rsrc_register { - pub nr: __u32, - pub resv: __u32, - pub resv2: __u64, - pub data: __u64, - pub tags: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_rsrc_register() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(io_uring_rsrc_register)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_rsrc_register)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_register), - "::", - stringify!(nr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_register), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_register), - "::", - stringify!(resv2) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_register), - "::", - stringify!(data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tags) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_register), - "::", - stringify!(tags) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_rsrc_update { - pub offset: __u32, - pub resv: __u32, - pub data: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_rsrc_update() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(io_uring_rsrc_update)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_rsrc_update)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update), - "::", - stringify!(offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update), - "::", - stringify!(data) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_rsrc_update2 { - pub offset: __u32, - pub resv: __u32, - pub data: __u64, - pub tags: __u64, - pub nr: __u32, - pub resv2: __u32, -} -#[test] -fn bindgen_test_layout_io_uring_rsrc_update2() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(io_uring_rsrc_update2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_rsrc_update2)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(data) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).tags) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(tags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(nr) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(io_uring_rsrc_update2), - "::", - stringify!(resv2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_probe_op { - pub op: __u8, - pub resv: __u8, - pub flags: __u16, - pub resv2: __u32, -} -#[test] -fn bindgen_test_layout_io_uring_probe_op() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(io_uring_probe_op)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(io_uring_probe_op)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe_op), - "::", - stringify!(op) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe_op), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe_op), - "::", - stringify!(flags) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe_op), - "::", - stringify!(resv2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Default)] -pub struct io_uring_probe { - pub last_op: __u8, - pub ops_len: __u8, - pub resv: __u16, - pub resv2: [__u32; 3usize], - pub ops: __IncompleteArrayField, -} -#[test] -fn bindgen_test_layout_io_uring_probe() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(io_uring_probe)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(io_uring_probe)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).last_op) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe), - "::", - stringify!(last_op) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ops_len) as usize - ptr as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe), - "::", - stringify!(ops_len) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe), - "::", - stringify!(resv2) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ops) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_uring_probe), - "::", - stringify!(ops) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct io_uring_restriction { - pub opcode: __u16, - pub __bindgen_anon_1: io_uring_restriction__bindgen_ty_1, - pub resv: __u8, - pub resv2: [__u32; 3usize], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union io_uring_restriction__bindgen_ty_1 { - pub register_op: __u8, - pub sqe_op: __u8, - pub sqe_flags: __u8, -} -#[test] -fn bindgen_test_layout_io_uring_restriction__bindgen_ty_1() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(io_uring_restriction__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!( - "Alignment of ", - stringify!(io_uring_restriction__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).register_op) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction__bindgen_ty_1), - "::", - stringify!(register_op) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sqe_op) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction__bindgen_ty_1), - "::", - stringify!(sqe_op) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sqe_flags) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction__bindgen_ty_1), - "::", - stringify!(sqe_flags) - ) - ); -} -impl Default for io_uring_restriction__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() - } - } -} -#[test] -fn bindgen_test_layout_io_uring_restriction() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(io_uring_restriction)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(io_uring_restriction)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).opcode) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction), - "::", - stringify!(opcode) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv) as usize - ptr as usize }, - 3usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction), - "::", - stringify!(resv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resv2) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(io_uring_restriction), - "::", - stringify!(resv2) - ) - ); -} -impl Default for io_uring_restriction { - fn default() -> Self { - let mut s = ::std::mem::MaybeUninit::::uninit(); - unsafe { - ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } -} -pub const IORING_RESTRICTION_REGISTER_OP: _bindgen_ty_6 = 0; -pub const IORING_RESTRICTION_SQE_OP: _bindgen_ty_6 = 1; -pub const IORING_RESTRICTION_SQE_FLAGS_ALLOWED: _bindgen_ty_6 = 2; -pub const IORING_RESTRICTION_SQE_FLAGS_REQUIRED: _bindgen_ty_6 = 3; -pub const IORING_RESTRICTION_LAST: _bindgen_ty_6 = 4; -pub type _bindgen_ty_6 = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Default, Copy, Clone, PartialEq)] -pub struct io_uring_getevents_arg { - pub sigmask: __u64, - pub sigmask_sz: __u32, - pub pad: __u32, - pub ts: __u64, -} -#[test] -fn bindgen_test_layout_io_uring_getevents_arg() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(io_uring_getevents_arg)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(io_uring_getevents_arg)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sigmask) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(io_uring_getevents_arg), - "::", - stringify!(sigmask) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sigmask_sz) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(io_uring_getevents_arg), - "::", - stringify!(sigmask_sz) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(io_uring_getevents_arg), - "::", - stringify!(pad) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ts) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(io_uring_getevents_arg), - "::", - stringify!(ts) - ) - ); -} diff --git a/src/vmm/src/io_uring/generated.rs b/src/vmm/src/io_uring/generated.rs new file mode 100644 index 00000000000..445f4a98237 --- /dev/null +++ b/src/vmm/src/io_uring/generated.rs @@ -0,0 +1,728 @@ +// 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 +)] + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +pub const IORING_SETUP_IOPOLL: u32 = 1; +pub const IORING_SETUP_SQPOLL: u32 = 2; +pub const IORING_SETUP_SQ_AFF: u32 = 4; +pub const IORING_SETUP_CQSIZE: u32 = 8; +pub const IORING_SETUP_CLAMP: u32 = 16; +pub const IORING_SETUP_ATTACH_WQ: u32 = 32; +pub const IORING_SETUP_R_DISABLED: u32 = 64; +pub const IORING_FSYNC_DATASYNC: u32 = 1; +pub const IORING_TIMEOUT_ABS: u32 = 1; +pub const IORING_TIMEOUT_UPDATE: u32 = 2; +pub const IORING_TIMEOUT_BOOTTIME: u32 = 4; +pub const IORING_TIMEOUT_REALTIME: u32 = 8; +pub const IORING_LINK_TIMEOUT_UPDATE: u32 = 16; +pub const IORING_TIMEOUT_CLOCK_MASK: u32 = 12; +pub const IORING_TIMEOUT_UPDATE_MASK: u32 = 18; +pub const IORING_POLL_ADD_MULTI: u32 = 1; +pub const IORING_POLL_UPDATE_EVENTS: u32 = 2; +pub const IORING_POLL_UPDATE_USER_DATA: u32 = 4; +pub const IORING_CQE_F_BUFFER: u32 = 1; +pub const IORING_CQE_F_MORE: u32 = 2; +pub const IORING_OFF_SQ_RING: u32 = 0; +pub const IORING_OFF_CQ_RING: u32 = 134217728; +pub const IORING_OFF_SQES: u32 = 268435456; +pub const IORING_SQ_NEED_WAKEUP: u32 = 1; +pub const IORING_SQ_CQ_OVERFLOW: u32 = 2; +pub const IORING_CQ_EVENTFD_DISABLED: u32 = 1; +pub const IORING_ENTER_GETEVENTS: u32 = 1; +pub const IORING_ENTER_SQ_WAKEUP: u32 = 2; +pub const IORING_ENTER_SQ_WAIT: u32 = 4; +pub const IORING_ENTER_EXT_ARG: u32 = 8; +pub const IORING_FEAT_SINGLE_MMAP: u32 = 1; +pub const IORING_FEAT_NODROP: u32 = 2; +pub const IORING_FEAT_SUBMIT_STABLE: u32 = 4; +pub const IORING_FEAT_RW_CUR_POS: u32 = 8; +pub const IORING_FEAT_CUR_PERSONALITY: u32 = 16; +pub const IORING_FEAT_FAST_POLL: u32 = 32; +pub const IORING_FEAT_POLL_32BITS: u32 = 64; +pub const IORING_FEAT_SQPOLL_NONFIXED: u32 = 128; +pub const IORING_FEAT_EXT_ARG: u32 = 256; +pub const IORING_FEAT_NATIVE_WORKERS: u32 = 512; +pub const IORING_FEAT_RSRC_TAGS: u32 = 1024; +pub const IORING_REGISTER_FILES_SKIP: i32 = -2; +pub const IO_URING_OP_SUPPORTED: u32 = 1; +pub type __u8 = ::std::os::raw::c_uchar; +pub type __u16 = ::std::os::raw::c_ushort; +pub type __s32 = ::std::os::raw::c_int; +pub type __u32 = ::std::os::raw::c_uint; +pub type __u64 = ::std::os::raw::c_ulonglong; +pub type __kernel_rwf_t = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct io_uring_sqe { + pub opcode: __u8, + pub flags: __u8, + pub ioprio: __u16, + pub fd: __s32, + pub __bindgen_anon_1: io_uring_sqe__bindgen_ty_1, + pub __bindgen_anon_2: io_uring_sqe__bindgen_ty_2, + pub len: __u32, + pub __bindgen_anon_3: io_uring_sqe__bindgen_ty_3, + pub user_data: __u64, + pub __bindgen_anon_4: io_uring_sqe__bindgen_ty_4, + pub personality: __u16, + pub __bindgen_anon_5: io_uring_sqe__bindgen_ty_5, + pub __pad2: [__u64; 2usize], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union io_uring_sqe__bindgen_ty_1 { + pub off: __u64, + pub addr2: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_sqe__bindgen_ty_1"] + [::std::mem::size_of::() - 8usize]; + ["Alignment of io_uring_sqe__bindgen_ty_1"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_1::off"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_1, off) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_1::addr2"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_1, addr2) - 0usize]; +}; +impl Default for io_uring_sqe__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() + } + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union io_uring_sqe__bindgen_ty_2 { + pub addr: __u64, + pub splice_off_in: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_sqe__bindgen_ty_2"] + [::std::mem::size_of::() - 8usize]; + ["Alignment of io_uring_sqe__bindgen_ty_2"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_2::addr"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_2, addr) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_2::splice_off_in"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_2, splice_off_in) - 0usize]; +}; +impl Default for io_uring_sqe__bindgen_ty_2 { + 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(Copy, Clone)] +pub union io_uring_sqe__bindgen_ty_3 { + pub rw_flags: __kernel_rwf_t, + pub fsync_flags: __u32, + pub poll_events: __u16, + pub poll32_events: __u32, + pub sync_range_flags: __u32, + pub msg_flags: __u32, + pub timeout_flags: __u32, + pub accept_flags: __u32, + pub cancel_flags: __u32, + pub open_flags: __u32, + pub statx_flags: __u32, + pub fadvise_advice: __u32, + pub splice_flags: __u32, + pub rename_flags: __u32, + pub unlink_flags: __u32, + pub hardlink_flags: __u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_sqe__bindgen_ty_3"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of io_uring_sqe__bindgen_ty_3"] + [::std::mem::align_of::() - 4usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::rw_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, rw_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::fsync_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, fsync_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::poll_events"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, poll_events) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::poll32_events"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, poll32_events) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::sync_range_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, sync_range_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::msg_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, msg_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::timeout_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, timeout_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::accept_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, accept_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::cancel_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, cancel_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::open_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, open_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::statx_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, statx_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::fadvise_advice"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, fadvise_advice) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::splice_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, splice_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::rename_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, rename_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::unlink_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, unlink_flags) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_3::hardlink_flags"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_3, hardlink_flags) - 0usize]; +}; +impl Default for io_uring_sqe__bindgen_ty_3 { + 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, packed)] +#[derive(Copy, Clone)] +pub union io_uring_sqe__bindgen_ty_4 { + pub buf_index: __u16, + pub buf_group: __u16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_sqe__bindgen_ty_4"] + [::std::mem::size_of::() - 2usize]; + ["Alignment of io_uring_sqe__bindgen_ty_4"] + [::std::mem::align_of::() - 1usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_4::buf_index"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_4, buf_index) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_4::buf_group"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_4, buf_group) - 0usize]; +}; +impl Default for io_uring_sqe__bindgen_ty_4 { + 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(Copy, Clone)] +pub union io_uring_sqe__bindgen_ty_5 { + pub splice_fd_in: __s32, + pub file_index: __u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_sqe__bindgen_ty_5"] + [::std::mem::size_of::() - 4usize]; + ["Alignment of io_uring_sqe__bindgen_ty_5"] + [::std::mem::align_of::() - 4usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_5::splice_fd_in"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_5, splice_fd_in) - 0usize]; + ["Offset of field: io_uring_sqe__bindgen_ty_5::file_index"] + [::std::mem::offset_of!(io_uring_sqe__bindgen_ty_5, file_index) - 0usize]; +}; +impl Default for io_uring_sqe__bindgen_ty_5 { + 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 io_uring_sqe"][::std::mem::size_of::() - 64usize]; + ["Alignment of io_uring_sqe"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_sqe::opcode"] + [::std::mem::offset_of!(io_uring_sqe, opcode) - 0usize]; + ["Offset of field: io_uring_sqe::flags"][::std::mem::offset_of!(io_uring_sqe, flags) - 1usize]; + ["Offset of field: io_uring_sqe::ioprio"] + [::std::mem::offset_of!(io_uring_sqe, ioprio) - 2usize]; + ["Offset of field: io_uring_sqe::fd"][::std::mem::offset_of!(io_uring_sqe, fd) - 4usize]; + ["Offset of field: io_uring_sqe::len"][::std::mem::offset_of!(io_uring_sqe, len) - 24usize]; + ["Offset of field: io_uring_sqe::user_data"] + [::std::mem::offset_of!(io_uring_sqe, user_data) - 32usize]; + ["Offset of field: io_uring_sqe::personality"] + [::std::mem::offset_of!(io_uring_sqe, personality) - 42usize]; + ["Offset of field: io_uring_sqe::__pad2"] + [::std::mem::offset_of!(io_uring_sqe, __pad2) - 48usize]; +}; +impl Default for io_uring_sqe { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const IOSQE_FIXED_FILE_BIT: _bindgen_ty_1 = 0; +pub const IOSQE_IO_DRAIN_BIT: _bindgen_ty_1 = 1; +pub const IOSQE_IO_LINK_BIT: _bindgen_ty_1 = 2; +pub const IOSQE_IO_HARDLINK_BIT: _bindgen_ty_1 = 3; +pub const IOSQE_ASYNC_BIT: _bindgen_ty_1 = 4; +pub const IOSQE_BUFFER_SELECT_BIT: _bindgen_ty_1 = 5; +pub type _bindgen_ty_1 = ::std::os::raw::c_uint; +pub const IORING_OP_NOP: _bindgen_ty_2 = 0; +pub const IORING_OP_READV: _bindgen_ty_2 = 1; +pub const IORING_OP_WRITEV: _bindgen_ty_2 = 2; +pub const IORING_OP_FSYNC: _bindgen_ty_2 = 3; +pub const IORING_OP_READ_FIXED: _bindgen_ty_2 = 4; +pub const IORING_OP_WRITE_FIXED: _bindgen_ty_2 = 5; +pub const IORING_OP_POLL_ADD: _bindgen_ty_2 = 6; +pub const IORING_OP_POLL_REMOVE: _bindgen_ty_2 = 7; +pub const IORING_OP_SYNC_FILE_RANGE: _bindgen_ty_2 = 8; +pub const IORING_OP_SENDMSG: _bindgen_ty_2 = 9; +pub const IORING_OP_RECVMSG: _bindgen_ty_2 = 10; +pub const IORING_OP_TIMEOUT: _bindgen_ty_2 = 11; +pub const IORING_OP_TIMEOUT_REMOVE: _bindgen_ty_2 = 12; +pub const IORING_OP_ACCEPT: _bindgen_ty_2 = 13; +pub const IORING_OP_ASYNC_CANCEL: _bindgen_ty_2 = 14; +pub const IORING_OP_LINK_TIMEOUT: _bindgen_ty_2 = 15; +pub const IORING_OP_CONNECT: _bindgen_ty_2 = 16; +pub const IORING_OP_FALLOCATE: _bindgen_ty_2 = 17; +pub const IORING_OP_OPENAT: _bindgen_ty_2 = 18; +pub const IORING_OP_CLOSE: _bindgen_ty_2 = 19; +pub const IORING_OP_FILES_UPDATE: _bindgen_ty_2 = 20; +pub const IORING_OP_STATX: _bindgen_ty_2 = 21; +pub const IORING_OP_READ: _bindgen_ty_2 = 22; +pub const IORING_OP_WRITE: _bindgen_ty_2 = 23; +pub const IORING_OP_FADVISE: _bindgen_ty_2 = 24; +pub const IORING_OP_MADVISE: _bindgen_ty_2 = 25; +pub const IORING_OP_SEND: _bindgen_ty_2 = 26; +pub const IORING_OP_RECV: _bindgen_ty_2 = 27; +pub const IORING_OP_OPENAT2: _bindgen_ty_2 = 28; +pub const IORING_OP_EPOLL_CTL: _bindgen_ty_2 = 29; +pub const IORING_OP_SPLICE: _bindgen_ty_2 = 30; +pub const IORING_OP_PROVIDE_BUFFERS: _bindgen_ty_2 = 31; +pub const IORING_OP_REMOVE_BUFFERS: _bindgen_ty_2 = 32; +pub const IORING_OP_TEE: _bindgen_ty_2 = 33; +pub const IORING_OP_SHUTDOWN: _bindgen_ty_2 = 34; +pub const IORING_OP_RENAMEAT: _bindgen_ty_2 = 35; +pub const IORING_OP_UNLINKAT: _bindgen_ty_2 = 36; +pub const IORING_OP_LAST: _bindgen_ty_2 = 37; +pub type _bindgen_ty_2 = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_cqe { + pub user_data: __u64, + pub res: __s32, + pub flags: __u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_cqe"][::std::mem::size_of::() - 16usize]; + ["Alignment of io_uring_cqe"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_cqe::user_data"] + [::std::mem::offset_of!(io_uring_cqe, user_data) - 0usize]; + ["Offset of field: io_uring_cqe::res"][::std::mem::offset_of!(io_uring_cqe, res) - 8usize]; + ["Offset of field: io_uring_cqe::flags"][::std::mem::offset_of!(io_uring_cqe, flags) - 12usize]; +}; +pub const IORING_CQE_BUFFER_SHIFT: _bindgen_ty_3 = 16; +pub type _bindgen_ty_3 = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_sqring_offsets { + pub head: __u32, + pub tail: __u32, + pub ring_mask: __u32, + pub ring_entries: __u32, + pub flags: __u32, + pub dropped: __u32, + pub array: __u32, + pub resv1: __u32, + pub resv2: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_sqring_offsets"][::std::mem::size_of::() - 40usize]; + ["Alignment of io_sqring_offsets"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_sqring_offsets::head"] + [::std::mem::offset_of!(io_sqring_offsets, head) - 0usize]; + ["Offset of field: io_sqring_offsets::tail"] + [::std::mem::offset_of!(io_sqring_offsets, tail) - 4usize]; + ["Offset of field: io_sqring_offsets::ring_mask"] + [::std::mem::offset_of!(io_sqring_offsets, ring_mask) - 8usize]; + ["Offset of field: io_sqring_offsets::ring_entries"] + [::std::mem::offset_of!(io_sqring_offsets, ring_entries) - 12usize]; + ["Offset of field: io_sqring_offsets::flags"] + [::std::mem::offset_of!(io_sqring_offsets, flags) - 16usize]; + ["Offset of field: io_sqring_offsets::dropped"] + [::std::mem::offset_of!(io_sqring_offsets, dropped) - 20usize]; + ["Offset of field: io_sqring_offsets::array"] + [::std::mem::offset_of!(io_sqring_offsets, array) - 24usize]; + ["Offset of field: io_sqring_offsets::resv1"] + [::std::mem::offset_of!(io_sqring_offsets, resv1) - 28usize]; + ["Offset of field: io_sqring_offsets::resv2"] + [::std::mem::offset_of!(io_sqring_offsets, resv2) - 32usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_cqring_offsets { + pub head: __u32, + pub tail: __u32, + pub ring_mask: __u32, + pub ring_entries: __u32, + pub overflow: __u32, + pub cqes: __u32, + pub flags: __u32, + pub resv1: __u32, + pub resv2: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_cqring_offsets"][::std::mem::size_of::() - 40usize]; + ["Alignment of io_cqring_offsets"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_cqring_offsets::head"] + [::std::mem::offset_of!(io_cqring_offsets, head) - 0usize]; + ["Offset of field: io_cqring_offsets::tail"] + [::std::mem::offset_of!(io_cqring_offsets, tail) - 4usize]; + ["Offset of field: io_cqring_offsets::ring_mask"] + [::std::mem::offset_of!(io_cqring_offsets, ring_mask) - 8usize]; + ["Offset of field: io_cqring_offsets::ring_entries"] + [::std::mem::offset_of!(io_cqring_offsets, ring_entries) - 12usize]; + ["Offset of field: io_cqring_offsets::overflow"] + [::std::mem::offset_of!(io_cqring_offsets, overflow) - 16usize]; + ["Offset of field: io_cqring_offsets::cqes"] + [::std::mem::offset_of!(io_cqring_offsets, cqes) - 20usize]; + ["Offset of field: io_cqring_offsets::flags"] + [::std::mem::offset_of!(io_cqring_offsets, flags) - 24usize]; + ["Offset of field: io_cqring_offsets::resv1"] + [::std::mem::offset_of!(io_cqring_offsets, resv1) - 28usize]; + ["Offset of field: io_cqring_offsets::resv2"] + [::std::mem::offset_of!(io_cqring_offsets, resv2) - 32usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_params { + pub sq_entries: __u32, + pub cq_entries: __u32, + pub flags: __u32, + pub sq_thread_cpu: __u32, + pub sq_thread_idle: __u32, + pub features: __u32, + pub wq_fd: __u32, + pub resv: [__u32; 3usize], + pub sq_off: io_sqring_offsets, + pub cq_off: io_cqring_offsets, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_params"][::std::mem::size_of::() - 120usize]; + ["Alignment of io_uring_params"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_params::sq_entries"] + [::std::mem::offset_of!(io_uring_params, sq_entries) - 0usize]; + ["Offset of field: io_uring_params::cq_entries"] + [::std::mem::offset_of!(io_uring_params, cq_entries) - 4usize]; + ["Offset of field: io_uring_params::flags"] + [::std::mem::offset_of!(io_uring_params, flags) - 8usize]; + ["Offset of field: io_uring_params::sq_thread_cpu"] + [::std::mem::offset_of!(io_uring_params, sq_thread_cpu) - 12usize]; + ["Offset of field: io_uring_params::sq_thread_idle"] + [::std::mem::offset_of!(io_uring_params, sq_thread_idle) - 16usize]; + ["Offset of field: io_uring_params::features"] + [::std::mem::offset_of!(io_uring_params, features) - 20usize]; + ["Offset of field: io_uring_params::wq_fd"] + [::std::mem::offset_of!(io_uring_params, wq_fd) - 24usize]; + ["Offset of field: io_uring_params::resv"] + [::std::mem::offset_of!(io_uring_params, resv) - 28usize]; + ["Offset of field: io_uring_params::sq_off"] + [::std::mem::offset_of!(io_uring_params, sq_off) - 40usize]; + ["Offset of field: io_uring_params::cq_off"] + [::std::mem::offset_of!(io_uring_params, cq_off) - 80usize]; +}; +pub const IORING_REGISTER_BUFFERS: _bindgen_ty_4 = 0; +pub const IORING_UNREGISTER_BUFFERS: _bindgen_ty_4 = 1; +pub const IORING_REGISTER_FILES: _bindgen_ty_4 = 2; +pub const IORING_UNREGISTER_FILES: _bindgen_ty_4 = 3; +pub const IORING_REGISTER_EVENTFD: _bindgen_ty_4 = 4; +pub const IORING_UNREGISTER_EVENTFD: _bindgen_ty_4 = 5; +pub const IORING_REGISTER_FILES_UPDATE: _bindgen_ty_4 = 6; +pub const IORING_REGISTER_EVENTFD_ASYNC: _bindgen_ty_4 = 7; +pub const IORING_REGISTER_PROBE: _bindgen_ty_4 = 8; +pub const IORING_REGISTER_PERSONALITY: _bindgen_ty_4 = 9; +pub const IORING_UNREGISTER_PERSONALITY: _bindgen_ty_4 = 10; +pub const IORING_REGISTER_RESTRICTIONS: _bindgen_ty_4 = 11; +pub const IORING_REGISTER_ENABLE_RINGS: _bindgen_ty_4 = 12; +pub const IORING_REGISTER_FILES2: _bindgen_ty_4 = 13; +pub const IORING_REGISTER_FILES_UPDATE2: _bindgen_ty_4 = 14; +pub const IORING_REGISTER_BUFFERS2: _bindgen_ty_4 = 15; +pub const IORING_REGISTER_BUFFERS_UPDATE: _bindgen_ty_4 = 16; +pub const IORING_REGISTER_IOWQ_AFF: _bindgen_ty_4 = 17; +pub const IORING_UNREGISTER_IOWQ_AFF: _bindgen_ty_4 = 18; +pub const IORING_REGISTER_IOWQ_MAX_WORKERS: _bindgen_ty_4 = 19; +pub const IORING_REGISTER_LAST: _bindgen_ty_4 = 20; +pub type _bindgen_ty_4 = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_files_update { + pub offset: __u32, + pub resv: __u32, + pub fds: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_files_update"][::std::mem::size_of::() - 16usize]; + ["Alignment of io_uring_files_update"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_files_update::offset"] + [::std::mem::offset_of!(io_uring_files_update, offset) - 0usize]; + ["Offset of field: io_uring_files_update::resv"] + [::std::mem::offset_of!(io_uring_files_update, resv) - 4usize]; + ["Offset of field: io_uring_files_update::fds"] + [::std::mem::offset_of!(io_uring_files_update, fds) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_rsrc_register { + pub nr: __u32, + pub resv: __u32, + pub resv2: __u64, + pub data: __u64, + pub tags: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_rsrc_register"][::std::mem::size_of::() - 32usize]; + ["Alignment of io_uring_rsrc_register"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_rsrc_register::nr"] + [::std::mem::offset_of!(io_uring_rsrc_register, nr) - 0usize]; + ["Offset of field: io_uring_rsrc_register::resv"] + [::std::mem::offset_of!(io_uring_rsrc_register, resv) - 4usize]; + ["Offset of field: io_uring_rsrc_register::resv2"] + [::std::mem::offset_of!(io_uring_rsrc_register, resv2) - 8usize]; + ["Offset of field: io_uring_rsrc_register::data"] + [::std::mem::offset_of!(io_uring_rsrc_register, data) - 16usize]; + ["Offset of field: io_uring_rsrc_register::tags"] + [::std::mem::offset_of!(io_uring_rsrc_register, tags) - 24usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_rsrc_update { + pub offset: __u32, + pub resv: __u32, + pub data: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_rsrc_update"][::std::mem::size_of::() - 16usize]; + ["Alignment of io_uring_rsrc_update"][::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_rsrc_update::offset"] + [::std::mem::offset_of!(io_uring_rsrc_update, offset) - 0usize]; + ["Offset of field: io_uring_rsrc_update::resv"] + [::std::mem::offset_of!(io_uring_rsrc_update, resv) - 4usize]; + ["Offset of field: io_uring_rsrc_update::data"] + [::std::mem::offset_of!(io_uring_rsrc_update, data) - 8usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_rsrc_update2 { + pub offset: __u32, + pub resv: __u32, + pub data: __u64, + pub tags: __u64, + pub nr: __u32, + pub resv2: __u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_rsrc_update2"][::std::mem::size_of::() - 32usize]; + ["Alignment of io_uring_rsrc_update2"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_rsrc_update2::offset"] + [::std::mem::offset_of!(io_uring_rsrc_update2, offset) - 0usize]; + ["Offset of field: io_uring_rsrc_update2::resv"] + [::std::mem::offset_of!(io_uring_rsrc_update2, resv) - 4usize]; + ["Offset of field: io_uring_rsrc_update2::data"] + [::std::mem::offset_of!(io_uring_rsrc_update2, data) - 8usize]; + ["Offset of field: io_uring_rsrc_update2::tags"] + [::std::mem::offset_of!(io_uring_rsrc_update2, tags) - 16usize]; + ["Offset of field: io_uring_rsrc_update2::nr"] + [::std::mem::offset_of!(io_uring_rsrc_update2, nr) - 24usize]; + ["Offset of field: io_uring_rsrc_update2::resv2"] + [::std::mem::offset_of!(io_uring_rsrc_update2, resv2) - 28usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_probe_op { + pub op: __u8, + pub resv: __u8, + pub flags: __u16, + pub resv2: __u32, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_probe_op"][::std::mem::size_of::() - 8usize]; + ["Alignment of io_uring_probe_op"][::std::mem::align_of::() - 4usize]; + ["Offset of field: io_uring_probe_op::op"] + [::std::mem::offset_of!(io_uring_probe_op, op) - 0usize]; + ["Offset of field: io_uring_probe_op::resv"] + [::std::mem::offset_of!(io_uring_probe_op, resv) - 1usize]; + ["Offset of field: io_uring_probe_op::flags"] + [::std::mem::offset_of!(io_uring_probe_op, flags) - 2usize]; + ["Offset of field: io_uring_probe_op::resv2"] + [::std::mem::offset_of!(io_uring_probe_op, resv2) - 4usize]; +}; +#[repr(C)] +#[derive(Debug, Default)] +pub struct io_uring_probe { + pub last_op: __u8, + pub ops_len: __u8, + pub resv: __u16, + pub resv2: [__u32; 3usize], + pub ops: __IncompleteArrayField, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_probe"][::std::mem::size_of::() - 16usize]; + ["Alignment of io_uring_probe"][::std::mem::align_of::() - 4usize]; + ["Offset of field: io_uring_probe::last_op"] + [::std::mem::offset_of!(io_uring_probe, last_op) - 0usize]; + ["Offset of field: io_uring_probe::ops_len"] + [::std::mem::offset_of!(io_uring_probe, ops_len) - 1usize]; + ["Offset of field: io_uring_probe::resv"] + [::std::mem::offset_of!(io_uring_probe, resv) - 2usize]; + ["Offset of field: io_uring_probe::resv2"] + [::std::mem::offset_of!(io_uring_probe, resv2) - 4usize]; + ["Offset of field: io_uring_probe::ops"][::std::mem::offset_of!(io_uring_probe, ops) - 16usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct io_uring_restriction { + pub opcode: __u16, + pub __bindgen_anon_1: io_uring_restriction__bindgen_ty_1, + pub resv: __u8, + pub resv2: [__u32; 3usize], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union io_uring_restriction__bindgen_ty_1 { + pub register_op: __u8, + pub sqe_op: __u8, + pub sqe_flags: __u8, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_restriction__bindgen_ty_1"] + [::std::mem::size_of::() - 1usize]; + ["Alignment of io_uring_restriction__bindgen_ty_1"] + [::std::mem::align_of::() - 1usize]; + ["Offset of field: io_uring_restriction__bindgen_ty_1::register_op"] + [::std::mem::offset_of!(io_uring_restriction__bindgen_ty_1, register_op) - 0usize]; + ["Offset of field: io_uring_restriction__bindgen_ty_1::sqe_op"] + [::std::mem::offset_of!(io_uring_restriction__bindgen_ty_1, sqe_op) - 0usize]; + ["Offset of field: io_uring_restriction__bindgen_ty_1::sqe_flags"] + [::std::mem::offset_of!(io_uring_restriction__bindgen_ty_1, sqe_flags) - 0usize]; +}; +impl Default for io_uring_restriction__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 io_uring_restriction"][::std::mem::size_of::() - 16usize]; + ["Alignment of io_uring_restriction"][::std::mem::align_of::() - 4usize]; + ["Offset of field: io_uring_restriction::opcode"] + [::std::mem::offset_of!(io_uring_restriction, opcode) - 0usize]; + ["Offset of field: io_uring_restriction::resv"] + [::std::mem::offset_of!(io_uring_restriction, resv) - 3usize]; + ["Offset of field: io_uring_restriction::resv2"] + [::std::mem::offset_of!(io_uring_restriction, resv2) - 4usize]; +}; +impl Default for io_uring_restriction { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +pub const IORING_RESTRICTION_REGISTER_OP: _bindgen_ty_6 = 0; +pub const IORING_RESTRICTION_SQE_OP: _bindgen_ty_6 = 1; +pub const IORING_RESTRICTION_SQE_FLAGS_ALLOWED: _bindgen_ty_6 = 2; +pub const IORING_RESTRICTION_SQE_FLAGS_REQUIRED: _bindgen_ty_6 = 3; +pub const IORING_RESTRICTION_LAST: _bindgen_ty_6 = 4; +pub type _bindgen_ty_6 = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct io_uring_getevents_arg { + pub sigmask: __u64, + pub sigmask_sz: __u32, + pub pad: __u32, + pub ts: __u64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of io_uring_getevents_arg"][::std::mem::size_of::() - 24usize]; + ["Alignment of io_uring_getevents_arg"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: io_uring_getevents_arg::sigmask"] + [::std::mem::offset_of!(io_uring_getevents_arg, sigmask) - 0usize]; + ["Offset of field: io_uring_getevents_arg::sigmask_sz"] + [::std::mem::offset_of!(io_uring_getevents_arg, sigmask_sz) - 8usize]; + ["Offset of field: io_uring_getevents_arg::pad"] + [::std::mem::offset_of!(io_uring_getevents_arg, pad) - 12usize]; + ["Offset of field: io_uring_getevents_arg::ts"] + [::std::mem::offset_of!(io_uring_getevents_arg, ts) - 16usize]; +}; diff --git a/src/vmm/src/io_uring/mod.rs b/src/vmm/src/io_uring/mod.rs index f306148044c..0de1abbf4eb 100644 --- a/src/vmm/src/io_uring/mod.rs +++ b/src/vmm/src/io_uring/mod.rs @@ -1,8 +1,7 @@ // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#[allow(clippy::undocumented_unsafe_blocks)] -mod gen; +mod generated; pub mod operation; mod probe; mod queue; @@ -14,7 +13,7 @@ use std::fs::File; use std::io::Error as IOError; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use gen::io_uring_params; +use generated::io_uring_params; use operation::{Cqe, FixedFd, OpCode, Operation}; use probe::{ProbeWrapper, PROBE_LEN}; pub use queue::completion::CQueueError; @@ -110,7 +109,7 @@ impl IoUring { ) -> Result { let mut params = io_uring_params { // Create the ring as disabled, so that we may register restrictions. - flags: gen::IORING_SETUP_R_DISABLED, + flags: generated::IORING_SETUP_R_DISABLED, ..Default::default() }; @@ -248,7 +247,7 @@ impl IoUring { libc::syscall( libc::SYS_io_uring_register, self.fd.as_raw_fd(), - gen::IORING_REGISTER_ENABLE_RINGS, + generated::IORING_REGISTER_ENABLE_RINGS, std::ptr::null::(), 0, ) @@ -273,7 +272,7 @@ impl IoUring { libc::syscall( libc::SYS_io_uring_register, self.fd.as_raw_fd(), - gen::IORING_REGISTER_FILES, + generated::IORING_REGISTER_FILES, files .iter() .map(|f| f.as_raw_fd()) @@ -297,7 +296,7 @@ impl IoUring { libc::syscall( libc::SYS_io_uring_register, self.fd.as_raw_fd(), - gen::IORING_REGISTER_EVENTFD, + generated::IORING_REGISTER_EVENTFD, (&fd) as *const _, 1, ) @@ -316,10 +315,10 @@ impl IoUring { libc::syscall( libc::SYS_io_uring_register, self.fd.as_raw_fd(), - gen::IORING_REGISTER_RESTRICTIONS, + generated::IORING_REGISTER_RESTRICTIONS, restrictions .iter() - .map(gen::io_uring_restriction::from) + .map(generated::io_uring_restriction::from) .collect::>() .as_mut_slice() .as_mut_ptr(), @@ -337,7 +336,7 @@ impl IoUring { // An alternative fix would be to keep an internal counter that tracks the number of // submitted entries that haven't been completed and makes sure it doesn't exceed // (2 * num_entries). - if (params.features & gen::IORING_FEAT_NODROP) == 0 { + if (params.features & generated::IORING_FEAT_NODROP) == 0 { return Err(IoUringError::UnsupportedFeature("IORING_FEAT_NODROP")); } @@ -352,7 +351,7 @@ impl IoUring { libc::syscall( libc::SYS_io_uring_register, self.fd.as_raw_fd(), - gen::IORING_REGISTER_PROBE, + generated::IORING_REGISTER_PROBE, probes.as_mut_fam_struct_ptr(), PROBE_LEN, ) @@ -363,7 +362,7 @@ impl IoUring { let supported_opcodes: HashSet = probes .as_slice() .iter() - .filter(|op| ((u32::from(op.flags)) & gen::IO_URING_OP_SUPPORTED) != 0) + .filter(|op| ((u32::from(op.flags)) & generated::IO_URING_OP_SUPPORTED) != 0) .map(|op| op.op) .collect(); diff --git a/src/vmm/src/io_uring/operation/cqe.rs b/src/vmm/src/io_uring/operation/cqe.rs index 2b4f4165e4c..bd445ecb28a 100644 --- a/src/vmm/src/io_uring/operation/cqe.rs +++ b/src/vmm/src/io_uring/operation/cqe.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; -use crate::io_uring::gen::io_uring_cqe; +use crate::io_uring::generated::io_uring_cqe; use crate::vstate::memory::ByteValued; // SAFETY: Struct is POD and contains no references or niches. diff --git a/src/vmm/src/io_uring/operation/mod.rs b/src/vmm/src/io_uring/operation/mod.rs index dc9cb958b3c..751a1ef835f 100644 --- a/src/vmm/src/io_uring/operation/mod.rs +++ b/src/vmm/src/io_uring/operation/mod.rs @@ -12,7 +12,7 @@ use std::fmt::{self, Debug}; pub use cqe::Cqe; pub(crate) use sqe::Sqe; -use crate::io_uring::gen::{self, io_uring_sqe, IOSQE_FIXED_FILE_BIT}; +use crate::io_uring::generated::{self, io_uring_sqe, IOSQE_FIXED_FILE_BIT}; /// The index of a registered fd. pub type FixedFd = u32; @@ -24,11 +24,11 @@ pub type FixedFd = u32; /// Supported operation types. pub enum OpCode { /// Read operation. - Read = gen::IORING_OP_READ as u8, + Read = generated::IORING_OP_READ as u8, /// Write operation. - Write = gen::IORING_OP_WRITE as u8, + Write = generated::IORING_OP_WRITE as u8, /// Fsync operation. - Fsync = gen::IORING_OP_FSYNC as u8, + Fsync = generated::IORING_OP_FSYNC as u8, } // Useful for outputting errors. @@ -120,7 +120,7 @@ impl Operation { // Needed for proptesting. #[cfg(test)] pub(crate) fn set_linked(&mut self) { - self.flags |= 1 << gen::IOSQE_IO_LINK_BIT; + self.flags |= 1 << generated::IOSQE_IO_LINK_BIT; } /// Transform the operation into an `Sqe`. diff --git a/src/vmm/src/io_uring/operation/sqe.rs b/src/vmm/src/io_uring/operation/sqe.rs index f405becd411..93c3be32d4c 100644 --- a/src/vmm/src/io_uring/operation/sqe.rs +++ b/src/vmm/src/io_uring/operation/sqe.rs @@ -3,7 +3,7 @@ use std::fmt::{self}; -use crate::io_uring::gen::io_uring_sqe; +use crate::io_uring::generated::io_uring_sqe; use crate::vstate::memory::ByteValued; // SAFETY: Struct is POD and contains no references or niches. diff --git a/src/vmm/src/io_uring/probe.rs b/src/vmm/src/io_uring/probe.rs index a1f74385815..4ac68daacef 100644 --- a/src/vmm/src/io_uring/probe.rs +++ b/src/vmm/src/io_uring/probe.rs @@ -4,7 +4,7 @@ use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; use vmm_sys_util::generate_fam_struct_impl; -use crate::io_uring::gen::{io_uring_probe, io_uring_probe_op}; +use crate::io_uring::generated::{io_uring_probe, io_uring_probe_op}; // There is no max for the number of operations returned by probing. So we fallback to using the // number of values representable in a u8; diff --git a/src/vmm/src/io_uring/queue/completion.rs b/src/vmm/src/io_uring/queue/completion.rs index 106229d032b..b225af7fa0e 100644 --- a/src/vmm/src/io_uring/queue/completion.rs +++ b/src/vmm/src/io_uring/queue/completion.rs @@ -9,7 +9,7 @@ use std::sync::atomic::Ordering; use vm_memory::{Bytes, VolatileMemory, VolatileMemoryError}; use super::mmap::{mmap, MmapError}; -use crate::io_uring::gen; +use crate::io_uring::generated; use crate::io_uring::operation::Cqe; use crate::vstate::memory::MmapRegion; @@ -43,15 +43,15 @@ pub(crate) struct CompletionQueue { impl CompletionQueue { pub(crate) fn new( io_uring_fd: RawFd, - params: &gen::io_uring_params, + params: &generated::io_uring_params, ) -> Result { let offsets = params.cq_off; // Map the CQ_ring. The actual size of the ring is `num_entries * size_of(entry_type)`. // To this we add an offset as per the io_uring specifications. let ring_size = (params.cq_off.cqes as usize) - + (params.cq_entries as usize) * std::mem::size_of::(); - let cqes = mmap(ring_size, io_uring_fd, gen::IORING_OFF_CQ_RING.into())?; + + (params.cq_entries as usize) * std::mem::size_of::(); + let cqes = mmap(ring_size, io_uring_fd, generated::IORING_OFF_CQ_RING.into())?; let ring = cqes.as_volatile_slice(); let ring_mask = ring.read_obj(offsets.ring_mask as usize)?; @@ -86,8 +86,8 @@ impl CompletionQueue { // validate that we have smth to fetch if Wrapping(unmasked_tail) - self.unmasked_head > Wrapping(0) { - let cqe: gen::io_uring_cqe = ring.read_obj( - self.cqes_off + (head as usize) * std::mem::size_of::(), + let cqe: generated::io_uring_cqe = ring.read_obj( + self.cqes_off + (head as usize) * std::mem::size_of::(), )?; // increase the head diff --git a/src/vmm/src/io_uring/queue/submission.rs b/src/vmm/src/io_uring/queue/submission.rs index c8306b40d26..4cef656a30c 100644 --- a/src/vmm/src/io_uring/queue/submission.rs +++ b/src/vmm/src/io_uring/queue/submission.rs @@ -12,7 +12,7 @@ use vm_memory::{VolatileMemory, VolatileMemoryError}; use vmm_sys_util::syscall::SyscallReturnCode; use super::mmap::{mmap, MmapError}; -use crate::io_uring::gen; +use crate::io_uring::generated; use crate::io_uring::operation::Sqe; use crate::vstate::memory::{Bytes, MmapRegion}; @@ -54,7 +54,7 @@ pub(crate) struct SubmissionQueue { impl SubmissionQueue { pub(crate) fn new( io_uring_fd: RawFd, - params: &gen::io_uring_params, + params: &generated::io_uring_params, ) -> Result { let (ring, sqes) = Self::mmap(io_uring_fd, params)?; let ring_slice = ring.as_volatile_slice(); @@ -102,7 +102,7 @@ impl SubmissionQueue { if let Err(err) = self .sqes .as_volatile_slice() - .write_obj(sqe.0, (tail as usize) * mem::size_of::()) + .write_obj(sqe.0, (tail as usize) * mem::size_of::()) { return Err((SQueueError::VolatileMemory(err), sqe.user_data())); } @@ -129,7 +129,7 @@ impl SubmissionQueue { let mut flags = 0; if min_complete > 0 { - flags |= gen::IORING_ENTER_GETEVENTS; + flags |= generated::IORING_ENTER_GETEVENTS; } // SAFETY: Safe because values are valid and we check the return value. let submitted = SyscallReturnCode(unsafe { @@ -155,19 +155,19 @@ impl SubmissionQueue { fn mmap( io_uring_fd: RawFd, - params: &gen::io_uring_params, + params: &generated::io_uring_params, ) -> Result<(MmapRegion, MmapRegion), SQueueError> { // map the SQ_ring. The actual size of the ring is `num_entries * size_of(entry_type)`. // To this we add an offset as per the io_uring specifications. let sqe_ring_size = (params.sq_off.array as usize) + (params.sq_entries as usize) * mem::size_of::(); - let sqe_ring = mmap(sqe_ring_size, io_uring_fd, gen::IORING_OFF_SQ_RING.into())?; + let sqe_ring = mmap(sqe_ring_size, io_uring_fd, generated::IORING_OFF_SQ_RING.into())?; // map the SQEs. - let sqes_array_size = (params.sq_entries as usize) * mem::size_of::(); + let sqes_array_size = (params.sq_entries as usize) * mem::size_of::(); - let sqes = mmap(sqes_array_size, io_uring_fd, gen::IORING_OFF_SQES.into())?; + let sqes = mmap(sqes_array_size, io_uring_fd, generated::IORING_OFF_SQES.into())?; Ok((sqe_ring, sqes)) } diff --git a/src/vmm/src/io_uring/restriction.rs b/src/vmm/src/io_uring/restriction.rs index f53478117df..54b8f5eefc8 100644 --- a/src/vmm/src/io_uring/restriction.rs +++ b/src/vmm/src/io_uring/restriction.rs @@ -12,7 +12,7 @@ use std::convert::From; -use crate::io_uring::gen; +use crate::io_uring::generated; use crate::io_uring::operation::OpCode; /// Adds support for restricting the operations allowed by io_uring. @@ -24,7 +24,7 @@ pub enum Restriction { RequireFixedFds, } -impl From<&Restriction> for gen::io_uring_restriction { +impl From<&Restriction> for generated::io_uring_restriction { fn from(restriction: &Restriction) -> Self { use Restriction::*; @@ -33,13 +33,13 @@ impl From<&Restriction> for gen::io_uring_restriction { match restriction { AllowOpCode(opcode) => { - instance.opcode = u16::try_from(gen::IORING_RESTRICTION_SQE_OP).unwrap(); + instance.opcode = u16::try_from(generated::IORING_RESTRICTION_SQE_OP).unwrap(); instance.__bindgen_anon_1.sqe_op = *opcode as u8; } RequireFixedFds => { instance.opcode = - u16::try_from(gen::IORING_RESTRICTION_SQE_FLAGS_REQUIRED).unwrap(); - instance.__bindgen_anon_1.sqe_flags = 1 << gen::IOSQE_FIXED_FILE_BIT; + u16::try_from(generated::IORING_RESTRICTION_SQE_FLAGS_REQUIRED).unwrap(); + instance.__bindgen_anon_1.sqe_flags = 1 << generated::IOSQE_FIXED_FILE_BIT; } }; diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 1cadab157a1..9871bd8ccc3 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -17,7 +17,7 @@ use log::{error, warn}; use serde::{Deserialize, Serialize}; use vmm_sys_util::fam::{self, FamStruct}; -use crate::arch::x86_64::gen::msr_index::{MSR_IA32_TSC, MSR_IA32_TSC_DEADLINE}; +use crate::arch::x86_64::generated::msr_index::{MSR_IA32_TSC, MSR_IA32_TSC_DEADLINE}; use crate::arch::x86_64::interrupts; use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError}; use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError}; diff --git a/tests/integration_tests/build/test_coverage.py b/tests/integration_tests/build/test_coverage.py index 9dbd97693f6..d8ce67fa6d7 100644 --- a/tests/integration_tests/build/test_coverage.py +++ b/tests/integration_tests/build/test_coverage.py @@ -63,7 +63,7 @@ def test_coverage(monkeypatch): --ignore "**/test_utils*" \ --ignore "**/mock_*" \ --ignore "src/firecracker/examples/*" \ - --ignore "**/gen*" \ + --ignore "**/generated*" \ -t lcov \ --ignore-not-existing \ -o {lcov_file}""" From c846b998efbc3f1f7cd66c7a5ae2f193905f1ddc Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:24:15 +0000 Subject: [PATCH 353/464] chore: switch to Rust 2024 edition All issues have been fixed in the previous commits, so finally switch to use 2024 edition. Signed-off-by: Riccardo Mancini --- src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 2 +- src/firecracker/Cargo.toml | 2 +- src/jailer/Cargo.toml | 2 +- src/log-instrument-macros/Cargo.toml | 2 +- src/log-instrument/Cargo.toml | 2 +- src/rebase-snap/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/utils/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index 717ec5d44c5..d98e8b93ded 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -2,7 +2,7 @@ name = "acpi_tables" version = "0.1.0" authors = ["The Cloud Hypervisor Authors", "Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 439f5730ee5..60bce291e42 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -2,7 +2,7 @@ name = "clippy-tracing" version = "0.1.0" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [[bin]] diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 5bc7358d8e1..c3838faab86 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -2,7 +2,7 @@ name = "cpu-template-helper" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [[bin]] diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml index ca0c6269252..17e1d8fcf2b 100644 --- a/src/firecracker/Cargo.toml +++ b/src/firecracker/Cargo.toml @@ -2,7 +2,7 @@ name = "firecracker" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" build = "build.rs" description = "Firecracker enables you to deploy workloads in lightweight virtual machines, called microVMs, which provide enhanced security and workload isolation over traditional VMs, while enabling the speed and resource efficiency of containers." homepage = "https://firecracker-microvm.github.io/" diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml index 935971c6d1a..7d83e0ed900 100644 --- a/src/jailer/Cargo.toml +++ b/src/jailer/Cargo.toml @@ -2,7 +2,7 @@ name = "jailer" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" description = "Process for starting Firecracker in production scenarios; applies a cgroup/namespace isolation barrier and then drops privileges." homepage = "https://firecracker-microvm.github.io/" license = "Apache-2.0" diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml index b8f6cac4ad1..0d2c564f668 100644 --- a/src/log-instrument-macros/Cargo.toml +++ b/src/log-instrument-macros/Cargo.toml @@ -2,7 +2,7 @@ name = "log-instrument-macros" version = "0.1.0" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" description = "Offers an attribute procedural macro that adds `log::trace!` events at the start and end of attributed functions." license = "Apache-2.0" diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index f1b71fd1a60..d42b1a7a4dc 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -2,7 +2,7 @@ name = "log-instrument" version = "0.3.0" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" description = "Offers an attribute procedural macro that adds `log::trace!` events at the start and end of attributed functions." license = "Apache-2.0" diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml index f121c6e2cd0..2e333208a75 100644 --- a/src/rebase-snap/Cargo.toml +++ b/src/rebase-snap/Cargo.toml @@ -2,7 +2,7 @@ name = "rebase-snap" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [[bin]] diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 5e50a3b2615..f183573d84d 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -2,7 +2,7 @@ name = "seccompiler" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" description = "Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file." homepage = "https://firecracker-microvm.github.io/" license = "Apache-2.0" diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 372ea2d72bb..106a4074501 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -2,7 +2,7 @@ name = "snapshot-editor" version = "1.12.0-dev" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [[bin]] diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml index 6d71fe47bf8..9db225fd610 100644 --- a/src/utils/Cargo.toml +++ b/src/utils/Cargo.toml @@ -2,7 +2,7 @@ name = "utils" version = "0.1.0" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [lib] diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 1224a00318a..34e35e2a4ef 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -2,7 +2,7 @@ name = "vmm" version = "0.1.0" authors = ["Amazon Firecracker team "] -edition = "2021" +edition = "2024" license = "Apache-2.0" [lib] From da878fb69f942b58e31823dd8eaa4dac845e6093 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Wed, 12 Mar 2025 17:37:03 +0000 Subject: [PATCH 354/464] chore: run cargo fmt on new edition The new rust edition comes with different opinions on how code should be formatted, mostly around ordering of dependencies. Let's fix it. Signed-off-by: Riccardo Mancini --- src/acpi-tables/src/aml.rs | 56 ++++---- src/acpi-tables/src/dsdt.rs | 2 +- src/acpi-tables/src/fadt.rs | 2 +- src/acpi-tables/src/madt.rs | 2 +- src/acpi-tables/src/rsdp.rs | 2 +- src/acpi-tables/src/xsdt.rs | 2 +- src/clippy-tracing/tests/integration_tests.rs | 2 +- .../src/template/dump/aarch64.rs | 4 +- .../src/template/dump/x86_64.rs | 2 +- .../src/template/strip/aarch64.rs | 2 +- .../src/template/strip/mod.rs | 2 +- .../src/template/strip/x86_64.rs | 2 +- .../src/template/verify/aarch64.rs | 2 +- .../src/template/verify/mod.rs | 2 +- .../src/template/verify/x86_64.rs | 6 +- src/cpu-template-helper/src/utils/mod.rs | 4 +- .../examples/uffd/fault_all_handler.rs | 2 +- src/firecracker/examples/uffd/uffd_utils.rs | 2 +- src/firecracker/src/api_server/mod.rs | 4 +- .../src/api_server/parsed_request.rs | 4 +- .../api_server/request/cpu_configuration.rs | 2 +- .../src/api_server/request/drive.rs | 2 +- .../request/machine_configuration.rs | 2 +- src/firecracker/src/api_server/request/net.rs | 2 +- .../src/api_server/request/snapshot.rs | 50 ++++--- src/firecracker/src/api_server_adapter.rs | 4 +- src/firecracker/src/main.rs | 4 +- src/firecracker/src/metrics.rs | 2 +- src/firecracker/src/seccomp.rs | 2 +- src/jailer/src/cgroup.rs | 10 +- src/jailer/src/chroot.rs | 2 +- src/jailer/src/env.rs | 10 +- src/jailer/src/main.rs | 2 +- src/log-instrument/examples/five.rs | 2 +- src/seccompiler/src/bin.rs | 2 +- src/snapshot-editor/src/edit_vmstate.rs | 2 +- src/snapshot-editor/src/main.rs | 6 +- src/utils/src/arg_parser.rs | 2 +- src/vmm/benches/block_request.rs | 2 +- src/vmm/benches/cpu_templates.rs | 4 +- src/vmm/benches/memory_access.rs | 2 +- src/vmm/benches/queue.rs | 2 +- src/vmm/src/acpi/mod.rs | 4 +- src/vmm/src/acpi/x86_64.rs | 2 +- src/vmm/src/arch/aarch64/cache_info.rs | 2 +- src/vmm/src/arch/aarch64/fdt.rs | 4 +- .../arch/aarch64/gic/gicv2/regs/dist_regs.rs | 4 +- .../arch/aarch64/gic/gicv2/regs/icc_regs.rs | 4 +- .../src/arch/aarch64/gic/gicv2/regs/mod.rs | 4 +- src/vmm/src/arch/aarch64/gic/gicv3/mod.rs | 2 +- .../arch/aarch64/gic/gicv3/regs/dist_regs.rs | 4 +- .../arch/aarch64/gic/gicv3/regs/icc_regs.rs | 4 +- .../src/arch/aarch64/gic/gicv3/regs/mod.rs | 4 +- .../aarch64/gic/gicv3/regs/redist_regs.rs | 4 +- src/vmm/src/arch/mod.rs | 14 +- src/vmm/src/arch/x86_64/mod.rs | 16 ++- src/vmm/src/arch/x86_64/mptable.rs | 2 +- src/vmm/src/arch/x86_64/msr.rs | 2 +- src/vmm/src/builder.rs | 133 ++++++++++-------- .../cpu_config/aarch64/custom_cpu_template.rs | 25 ++-- src/vmm/src/cpu_config/templates.rs | 6 +- src/vmm/src/cpu_config/templates_serde.rs | 2 +- .../cpu_config/x86_64/cpuid/amd/normalize.rs | 8 +- .../x86_64/cpuid/intel/normalize.rs | 6 +- src/vmm/src/cpu_config/x86_64/cpuid/mod.rs | 28 ++-- .../src/cpu_config/x86_64/cpuid/normalize.rs | 2 +- .../cpu_config/x86_64/custom_cpu_template.rs | 25 ++-- src/vmm/src/device_manager/acpi.rs | 2 +- src/vmm/src/device_manager/legacy.rs | 2 +- src/vmm/src/device_manager/mmio.rs | 30 ++-- src/vmm/src/device_manager/persist.rs | 10 +- src/vmm/src/devices/acpi/vmgenid.rs | 2 +- src/vmm/src/devices/legacy/i8042.rs | 2 +- src/vmm/src/devices/legacy/mod.rs | 4 +- src/vmm/src/devices/legacy/rtc_pl031.rs | 2 +- src/vmm/src/devices/virtio/balloon/device.rs | 4 +- .../devices/virtio/balloon/event_handler.rs | 4 +- src/vmm/src/devices/virtio/balloon/persist.rs | 6 +- .../src/devices/virtio/balloon/test_utils.rs | 2 +- src/vmm/src/devices/virtio/balloon/util.rs | 6 +- src/vmm/src/devices/virtio/block/device.rs | 2 +- .../devices/virtio/block/vhost_user/device.rs | 8 +- .../virtio/block/vhost_user/persist.rs | 4 +- .../src/devices/virtio/block/virtio/device.rs | 12 +- .../virtio/block/virtio/event_handler.rs | 2 +- .../virtio/block/virtio/io/async_io.rs | 2 +- .../devices/virtio/block/virtio/persist.rs | 6 +- .../devices/virtio/block/virtio/request.rs | 10 +- .../devices/virtio/block/virtio/test_utils.rs | 2 +- src/vmm/src/devices/virtio/device.rs | 4 +- src/vmm/src/devices/virtio/iovec.rs | 8 +- src/vmm/src/devices/virtio/mmio.rs | 2 +- src/vmm/src/devices/virtio/net/device.rs | 50 ++++--- .../src/devices/virtio/net/event_handler.rs | 4 +- src/vmm/src/devices/virtio/net/persist.rs | 6 +- src/vmm/src/devices/virtio/net/tap.rs | 7 +- src/vmm/src/devices/virtio/net/test_utils.rs | 18 ++- src/vmm/src/devices/virtio/persist.rs | 4 +- src/vmm/src/devices/virtio/queue.rs | 20 +-- src/vmm/src/devices/virtio/rng/device.rs | 10 +- src/vmm/src/devices/virtio/rng/persist.rs | 4 +- src/vmm/src/devices/virtio/vhost_user.rs | 2 +- .../src/devices/virtio/vhost_user_metrics.rs | 2 +- .../devices/virtio/vsock/csm/connection.rs | 4 +- src/vmm/src/devices/virtio/vsock/csm/txbuf.rs | 2 +- src/vmm/src/devices/virtio/vsock/device.rs | 8 +- .../src/devices/virtio/vsock/event_handler.rs | 2 +- src/vmm/src/devices/virtio/vsock/mod.rs | 2 +- src/vmm/src/devices/virtio/vsock/packet.rs | 4 +- src/vmm/src/devices/virtio/vsock/persist.rs | 2 +- .../src/devices/virtio/vsock/unix/muxer.rs | 2 +- .../devices/virtio/vsock/unix/muxer_killq.rs | 2 +- .../devices/virtio/vsock/unix/muxer_rxq.rs | 2 +- src/vmm/src/dumbo/mod.rs | 6 +- src/vmm/src/dumbo/pdu/arp.rs | 2 +- src/vmm/src/dumbo/pdu/ethernet.rs | 2 +- src/vmm/src/dumbo/pdu/ipv4.rs | 2 +- src/vmm/src/dumbo/pdu/tcp.rs | 4 +- src/vmm/src/dumbo/tcp/connection.rs | 6 +- src/vmm/src/dumbo/tcp/endpoint.rs | 12 +- src/vmm/src/gdb/arch/aarch64.rs | 8 +- src/vmm/src/gdb/arch/x86.rs | 2 +- src/vmm/src/gdb/event_loop.rs | 4 +- src/vmm/src/gdb/mod.rs | 2 +- src/vmm/src/gdb/target.rs | 12 +- src/vmm/src/io_uring/mod.rs | 2 +- src/vmm/src/io_uring/operation/mod.rs | 2 +- src/vmm/src/io_uring/queue/completion.rs | 2 +- src/vmm/src/io_uring/queue/submission.rs | 26 ++-- src/vmm/src/lib.rs | 4 +- src/vmm/src/logger/metrics.rs | 4 +- src/vmm/src/logger/mod.rs | 12 +- src/vmm/src/mmds/data_store.rs | 2 +- src/vmm/src/mmds/mod.rs | 2 +- src/vmm/src/mmds/ns.rs | 10 +- src/vmm/src/mmds/persist.rs | 2 +- src/vmm/src/mmds/token.rs | 2 +- src/vmm/src/persist.rs | 12 +- src/vmm/src/rate_limiter/persist.rs | 80 ++++++----- src/vmm/src/resources.rs | 6 +- src/vmm/src/rpc_interface.rs | 8 +- src/vmm/src/signal_handler.rs | 6 +- src/vmm/src/vmm_config/balloon.rs | 2 +- src/vmm/src/vmm_config/drive.rs | 18 ++- src/vmm/src/vmm_config/instance_info.rs | 2 +- src/vmm/src/vmm_config/net.rs | 2 +- src/vmm/src/vstate/kvm.rs | 20 +-- src/vmm/src/vstate/memory.rs | 10 +- src/vmm/src/vstate/vcpu/aarch64.rs | 14 +- src/vmm/src/vstate/vcpu/mod.rs | 16 +-- src/vmm/src/vstate/vcpu/x86_64.rs | 29 ++-- src/vmm/src/vstate/vm/aarch64.rs | 2 +- src/vmm/src/vstate/vm/mod.rs | 4 +- src/vmm/src/vstate/vm/x86_64.rs | 6 +- src/vmm/tests/integration_tests.rs | 2 +- 155 files changed, 644 insertions(+), 557 deletions(-) diff --git a/src/acpi-tables/src/aml.rs b/src/acpi-tables/src/aml.rs index 2c391bda65e..5c7e91a2d6a 100644 --- a/src/acpi-tables/src/aml.rs +++ b/src/acpi-tables/src/aml.rs @@ -1263,15 +1263,17 @@ mod tests { assert_eq!( Scope::new( "_SB_.MBRD".try_into().unwrap(), - vec![&Name::new( - "_CRS".try_into().unwrap(), - &ResourceTemplate::new(vec![&Memory32Fixed::new( - true, - 0xE800_0000, - 0x1000_0000 - )]) - ) - .unwrap()] + vec![ + &Name::new( + "_CRS".try_into().unwrap(), + &ResourceTemplate::new(vec![&Memory32Fixed::new( + true, + 0xE800_0000, + 0x1000_0000 + )]) + ) + .unwrap() + ] ) .to_aml_bytes() .unwrap(), @@ -1438,13 +1440,15 @@ mod tests { assert_eq!( Name::new( "_CRS".try_into().unwrap(), - &ResourceTemplate::new(vec![&AddressSpace::new_memory( - AddressSpaceCacheable::Cacheable, - true, - 0x8_0000_0000u64, - 0xf_ffff_ffffu64 - ) - .unwrap()]) + &ResourceTemplate::new(vec![ + &AddressSpace::new_memory( + AddressSpaceCacheable::Cacheable, + true, + 0x8_0000_0000u64, + 0xf_ffff_ffffu64 + ) + .unwrap() + ]) ) .unwrap() .to_aml_bytes() @@ -1553,7 +1557,9 @@ mod tests { (&"_SB_.PCI0._HID".try_into().unwrap() as &Path) .to_aml_bytes() .unwrap(), - [0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x5F, 0x48, 0x49, 0x44] + [ + 0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x5F, 0x48, 0x49, 0x44 + ] ); } @@ -2007,13 +2013,15 @@ mod tests { vec![ &Name::new( "MR64".try_into().unwrap(), - &ResourceTemplate::new(vec![&AddressSpace::new_memory( - AddressSpaceCacheable::Cacheable, - true, - 0x0000_0000_0000_0000u64, - 0xFFFF_FFFF_FFFF_FFFEu64 - ) - .unwrap()]) + &ResourceTemplate::new(vec![ + &AddressSpace::new_memory( + AddressSpaceCacheable::Cacheable, + true, + 0x0000_0000_0000_0000u64, + 0xFFFF_FFFF_FFFF_FFFEu64 + ) + .unwrap() + ]) ) .unwrap(), &CreateField::::new( diff --git a/src/acpi-tables/src/dsdt.rs b/src/acpi-tables/src/dsdt.rs index 49b05918937..dfb7c9b1b84 100644 --- a/src/acpi-tables/src/dsdt.rs +++ b/src/acpi-tables/src/dsdt.rs @@ -6,7 +6,7 @@ use std::mem::size_of; use vm_memory::{Address, Bytes, GuestAddress, GuestMemory}; use zerocopy::IntoBytes; -use crate::{checksum, AcpiError, Result, Sdt, SdtHeader}; +use crate::{AcpiError, Result, Sdt, SdtHeader, checksum}; /// Differentiated System Description Table (DSDT) /// diff --git a/src/acpi-tables/src/fadt.rs b/src/acpi-tables/src/fadt.rs index 1c937d5cc1b..c14f62bf230 100644 --- a/src/acpi-tables/src/fadt.rs +++ b/src/acpi-tables/src/fadt.rs @@ -7,7 +7,7 @@ use vm_memory::{Bytes, GuestAddress, GuestMemory}; use zerocopy::little_endian::{U16, U32, U64}; use zerocopy::{Immutable, IntoBytes}; -use crate::{checksum, GenericAddressStructure, Result, Sdt, SdtHeader}; +use crate::{GenericAddressStructure, Result, Sdt, SdtHeader, checksum}; #[cfg(target_arch = "x86_64")] pub const IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT: u16 = 2; diff --git a/src/acpi-tables/src/madt.rs b/src/acpi-tables/src/madt.rs index c7a11161f5d..eaef031e337 100644 --- a/src/acpi-tables/src/madt.rs +++ b/src/acpi-tables/src/madt.rs @@ -9,7 +9,7 @@ use vm_memory::{Address, Bytes, GuestAddress, GuestMemory}; use zerocopy::little_endian::U32; use zerocopy::{Immutable, IntoBytes}; -use crate::{checksum, AcpiError, Result, Sdt, SdtHeader}; +use crate::{AcpiError, Result, Sdt, SdtHeader, checksum}; const MADT_CPU_ENABLE_FLAG: u32 = 0; diff --git a/src/acpi-tables/src/rsdp.rs b/src/acpi-tables/src/rsdp.rs index b2318c6688d..06b3dfda4a3 100644 --- a/src/acpi-tables/src/rsdp.rs +++ b/src/acpi-tables/src/rsdp.rs @@ -8,7 +8,7 @@ use vm_memory::{Bytes, GuestAddress, GuestMemory}; use zerocopy::little_endian::{U32, U64}; use zerocopy::{Immutable, IntoBytes}; -use crate::{checksum, Result, Sdt}; +use crate::{Result, Sdt, checksum}; // clippy doesn't understand that we actually "use" the fields of this struct when we serialize // them as bytes in guest memory, so here we just ignore dead code to avoid having to name diff --git a/src/acpi-tables/src/xsdt.rs b/src/acpi-tables/src/xsdt.rs index ed6798c1137..a11cadc6f75 100644 --- a/src/acpi-tables/src/xsdt.rs +++ b/src/acpi-tables/src/xsdt.rs @@ -8,7 +8,7 @@ use std::mem::size_of; use vm_memory::{Address, Bytes, GuestAddress, GuestMemory}; use zerocopy::IntoBytes; -use crate::{checksum, AcpiError, Result, Sdt, SdtHeader}; +use crate::{AcpiError, Result, Sdt, SdtHeader, checksum}; /// Extended System Description Table (XSDT) /// diff --git a/src/clippy-tracing/tests/integration_tests.rs b/src/clippy-tracing/tests/integration_tests.rs index 1a7af70dc7c..b62f08a1f2a 100644 --- a/src/clippy-tracing/tests/integration_tests.rs +++ b/src/clippy-tracing/tests/integration_tests.rs @@ -1,7 +1,7 @@ // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use std::fs::{remove_file, OpenOptions}; +use std::fs::{OpenOptions, remove_file}; use std::io::{Read, Write}; use std::process::Command; diff --git a/src/cpu-template-helper/src/template/dump/aarch64.rs b/src/cpu-template-helper/src/template/dump/aarch64.rs index 8fd44ddcd14..3456298f521 100644 --- a/src/cpu-template-helper/src/template/dump/aarch64.rs +++ b/src/cpu-template-helper/src/template/dump/aarch64.rs @@ -1,7 +1,7 @@ // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use vmm::arch::aarch64::regs::{RegSize, PC, SYS_CNTPCT_EL0, SYS_CNTV_CVAL_EL0}; +use vmm::arch::aarch64::regs::{PC, RegSize, SYS_CNTPCT_EL0, SYS_CNTV_CVAL_EL0}; use vmm::cpu_config::aarch64::custom_cpu_template::RegisterModifier; use vmm::cpu_config::templates::{CpuConfiguration, CustomCpuTemplate, RegisterValueFilter}; use vmm::logger::warn; @@ -50,7 +50,7 @@ const REG_EXCLUSION_LIST: [u64; 3] = [ #[cfg(test)] mod tests { - use vmm::arch::aarch64::regs::{reg_size, Aarch64RegisterRef, Aarch64RegisterVec}; + use vmm::arch::aarch64::regs::{Aarch64RegisterRef, Aarch64RegisterVec, reg_size}; use super::*; diff --git a/src/cpu-template-helper/src/template/dump/x86_64.rs b/src/cpu-template-helper/src/template/dump/x86_64.rs index 8d97080d5e7..eaa2553a658 100644 --- a/src/cpu-template-helper/src/template/dump/x86_64.rs +++ b/src/cpu-template-helper/src/template/dump/x86_64.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; +use vmm::MSR_RANGE; use vmm::arch::x86_64::generated::msr_index::*; use vmm::arch::x86_64::msr::MsrRange; use vmm::cpu_config::templates::{CpuConfiguration, CustomCpuTemplate, RegisterValueFilter}; @@ -11,7 +12,6 @@ use vmm::cpu_config::x86_64::cpuid::{Cpuid, VENDOR_ID_AMD}; use vmm::cpu_config::x86_64::custom_cpu_template::{ CpuidLeafModifier, CpuidRegister, CpuidRegisterModifier, RegisterModifier, }; -use vmm::MSR_RANGE; use crate::utils::x86_64::{cpuid_leaf_modifier, cpuid_reg_modifier, msr_modifier}; diff --git a/src/cpu-template-helper/src/template/strip/aarch64.rs b/src/cpu-template-helper/src/template/strip/aarch64.rs index 3465bc919ba..d22217e6077 100644 --- a/src/cpu-template-helper/src/template/strip/aarch64.rs +++ b/src/cpu-template-helper/src/template/strip/aarch64.rs @@ -4,7 +4,7 @@ use vmm::cpu_config::aarch64::custom_cpu_template::RegisterModifier; use vmm::cpu_config::templates::CustomCpuTemplate; -use crate::template::strip::{strip_common, StripError}; +use crate::template::strip::{StripError, strip_common}; use crate::utils::aarch64::RegModifierMap; #[allow(dead_code)] diff --git a/src/cpu-template-helper/src/template/strip/mod.rs b/src/cpu-template-helper/src/template/strip/mod.rs index 1777d1d571b..81e6539e098 100644 --- a/src/cpu-template-helper/src/template/strip/mod.rs +++ b/src/cpu-template-helper/src/template/strip/mod.rs @@ -86,7 +86,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::utils::tests::{mock_modifier, MockModifierMapKey}; + use crate::utils::tests::{MockModifierMapKey, mock_modifier}; #[test] fn test_strip_common_with_single_input() { diff --git a/src/cpu-template-helper/src/template/strip/x86_64.rs b/src/cpu-template-helper/src/template/strip/x86_64.rs index a9db18fc15b..69c93d3df81 100644 --- a/src/cpu-template-helper/src/template/strip/x86_64.rs +++ b/src/cpu-template-helper/src/template/strip/x86_64.rs @@ -4,7 +4,7 @@ use vmm::cpu_config::templates::CustomCpuTemplate; use vmm::cpu_config::x86_64::custom_cpu_template::{CpuidLeafModifier, RegisterModifier}; -use crate::template::strip::{strip_common, StripError}; +use crate::template::strip::{StripError, strip_common}; use crate::utils::x86_64::{CpuidModifierMap, MsrModifierMap}; #[allow(dead_code)] diff --git a/src/cpu-template-helper/src/template/verify/aarch64.rs b/src/cpu-template-helper/src/template/verify/aarch64.rs index 19a76fadcb0..48d50f10de3 100644 --- a/src/cpu-template-helper/src/template/verify/aarch64.rs +++ b/src/cpu-template-helper/src/template/verify/aarch64.rs @@ -3,7 +3,7 @@ use vmm::cpu_config::templates::CustomCpuTemplate; -use super::{verify_common, VerifyError}; +use super::{VerifyError, verify_common}; use crate::utils::aarch64::RegModifierMap; pub fn verify( diff --git a/src/cpu-template-helper/src/template/verify/mod.rs b/src/cpu-template-helper/src/template/verify/mod.rs index e168d2816c4..1a83f6ba1b2 100644 --- a/src/cpu-template-helper/src/template/verify/mod.rs +++ b/src/cpu-template-helper/src/template/verify/mod.rs @@ -62,7 +62,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::utils::tests::{mock_modifier, MockModifierMapKey}; + use crate::utils::tests::{MockModifierMapKey, mock_modifier}; #[test] fn test_verify_modifier_map_with_non_existing_key() { diff --git a/src/cpu-template-helper/src/template/verify/x86_64.rs b/src/cpu-template-helper/src/template/verify/x86_64.rs index 9885b16898f..12aa4f3a0cc 100644 --- a/src/cpu-template-helper/src/template/verify/x86_64.rs +++ b/src/cpu-template-helper/src/template/verify/x86_64.rs @@ -3,7 +3,7 @@ use vmm::cpu_config::templates::CustomCpuTemplate; -use super::{verify_common, VerifyError}; +use super::{VerifyError, verify_common}; use crate::utils::x86_64::{CpuidModifierMap, MsrModifierMap}; pub fn verify( @@ -34,8 +34,8 @@ mod tests { use super::*; use crate::utils::x86_64::{ - cpuid_leaf_modifier, cpuid_reg_modifier, msr_modifier, CpuidModifierMapKey, - MsrModifierMapKey, + CpuidModifierMapKey, MsrModifierMapKey, cpuid_leaf_modifier, cpuid_reg_modifier, + msr_modifier, }; macro_rules! cpuid_modifier_map { diff --git a/src/cpu-template-helper/src/utils/mod.rs b/src/cpu-template-helper/src/utils/mod.rs index b6d3465efd5..f23871df1a9 100644 --- a/src/cpu-template-helper/src/utils/mod.rs +++ b/src/cpu-template-helper/src/utils/mod.rs @@ -9,12 +9,12 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; -use vmm::builder::{build_microvm_for_boot, StartMicrovmError}; +use vmm::builder::{StartMicrovmError, build_microvm_for_boot}; use vmm::cpu_config::templates::{CustomCpuTemplate, Numeric}; use vmm::resources::VmResources; use vmm::seccomp::get_empty_filters; use vmm::vmm_config::instance_info::{InstanceInfo, VmState}; -use vmm::{EventManager, Vmm, HTTP_MAX_PAYLOAD_SIZE}; +use vmm::{EventManager, HTTP_MAX_PAYLOAD_SIZE, Vmm}; use vmm_sys_util::tempfile::TempFile; #[cfg(target_arch = "aarch64")] diff --git a/src/firecracker/examples/uffd/fault_all_handler.rs b/src/firecracker/examples/uffd/fault_all_handler.rs index 6711350497a..ca7601ebf25 100644 --- a/src/firecracker/examples/uffd/fault_all_handler.rs +++ b/src/firecracker/examples/uffd/fault_all_handler.rs @@ -11,7 +11,7 @@ use std::fs::File; use std::os::unix::net::UnixListener; use uffd_utils::{Runtime, UffdHandler}; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; fn main() { let mut args = std::env::args(); diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index a24fd4feaaf..ccb4938ef01 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -149,7 +149,7 @@ impl UffdHandler { Err(Error::PartiallyCopied(bytes_copied)) if bytes_copied == 0 || bytes_copied == (-libc::EAGAIN) as usize => { - return false + return false; } Err(Error::CopyFailed(errno)) if std::io::Error::from(errno).raw_os_error().unwrap() == libc::EEXIST => diff --git a/src/firecracker/src/api_server/mod.rs b/src/firecracker/src/api_server/mod.rs index a2edce205cd..3dd9e417e71 100644 --- a/src/firecracker/src/api_server/mod.rs +++ b/src/firecracker/src/api_server/mod.rs @@ -15,9 +15,9 @@ use std::sync::mpsc; pub use micro_http::{Body, HttpServer, Request, Response, ServerError, StatusCode, Version}; use parsed_request::{ParsedRequest, RequestAction}; use serde_json::json; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; use vmm::logger::{ - debug, error, info, update_metric_with_elapsed_time, warn, ProcessTimeReporter, METRICS, + METRICS, ProcessTimeReporter, debug, error, info, update_metric_with_elapsed_time, warn, }; use vmm::rpc_interface::{ApiRequest, ApiResponse, VmmAction}; use vmm::seccomp::BpfProgramRef; diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs index 7313419bc9b..10d5c3d97ea 100644 --- a/src/firecracker/src/api_server/parsed_request.rs +++ b/src/firecracker/src/api_server/parsed_request.rs @@ -6,9 +6,10 @@ use std::fmt::Debug; use micro_http::{Body, Method, Request, Response, StatusCode, Version}; use serde::ser::Serialize; use serde_json::Value; -use vmm::logger::{error, info, log_enabled, Level}; +use vmm::logger::{Level, error, info, log_enabled}; use vmm::rpc_interface::{VmmAction, VmmActionError, VmmData}; +use super::ApiServer; use super::request::actions::parse_put_actions; use super::request::balloon::{parse_get_balloon, parse_patch_balloon, parse_put_balloon}; use super::request::boot_source::parse_put_boot_source; @@ -26,7 +27,6 @@ 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 super::ApiServer; #[derive(Debug)] pub(crate) enum RequestAction { diff --git a/src/firecracker/src/api_server/request/cpu_configuration.rs b/src/firecracker/src/api_server/request/cpu_configuration.rs index 649182bdf7c..454df80be4b 100644 --- a/src/firecracker/src/api_server/request/cpu_configuration.rs +++ b/src/firecracker/src/api_server/request/cpu_configuration.rs @@ -23,7 +23,7 @@ pub(crate) fn parse_put_cpu_config(body: &Body) -> Result Result { diff --git a/src/firecracker/src/api_server/request/net.rs b/src/firecracker/src/api_server/request/net.rs index 5fced98635c..a0125add274 100644 --- a/src/firecracker/src/api_server/request/net.rs +++ b/src/firecracker/src/api_server/request/net.rs @@ -5,7 +5,7 @@ use vmm::logger::{IncMetric, METRICS}; use vmm::rpc_interface::VmmAction; use vmm::vmm_config::net::{NetworkInterfaceConfig, NetworkInterfaceUpdateConfig}; -use super::super::parsed_request::{checked_id, ParsedRequest, RequestError}; +use super::super::parsed_request::{ParsedRequest, RequestError, checked_id}; use super::{Body, StatusCode}; pub(crate) fn parse_put_net( diff --git a/src/firecracker/src/api_server/request/snapshot.rs b/src/firecracker/src/api_server/request/snapshot.rs index 8878c224b5c..37a66f80093 100644 --- a/src/firecracker/src/api_server/request/snapshot.rs +++ b/src/firecracker/src/api_server/request/snapshot.rs @@ -66,13 +66,13 @@ fn parse_put_snapshot_load(body: &Body) -> Result { (Some(_), Some(_)) => { return Err(RequestError::SerdeJson(serde_json::Error::custom( TOO_MANY_FIELDS, - ))) + ))); } // Ensure that one of `mem_file_path` or `mem_backend` fields is always specified. (None, None) => { return Err(RequestError::SerdeJson(serde_json::Error::custom( MISSING_FIELD, - ))) + ))); } _ => {} } @@ -183,10 +183,12 @@ mod tests { resume_vm: false, }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); - assert!(parsed_request - .parsing_info() - .take_deprecation_message() - .is_none()); + assert!( + parsed_request + .parsing_info() + .take_deprecation_message() + .is_none() + ); assert_eq!( vmm_action_from_request(parsed_request), VmmAction::LoadSnapshot(expected_config) @@ -210,10 +212,12 @@ mod tests { resume_vm: false, }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); - assert!(parsed_request - .parsing_info() - .take_deprecation_message() - .is_none()); + assert!( + parsed_request + .parsing_info() + .take_deprecation_message() + .is_none() + ); assert_eq!( vmm_action_from_request(parsed_request), VmmAction::LoadSnapshot(expected_config) @@ -237,10 +241,12 @@ mod tests { resume_vm: true, }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); - assert!(parsed_request - .parsing_info() - .take_deprecation_message() - .is_none()); + assert!( + parsed_request + .parsing_info() + .take_deprecation_message() + .is_none() + ); assert_eq!( vmm_action_from_request(parsed_request), VmmAction::LoadSnapshot(expected_config) @@ -348,16 +354,20 @@ mod tests { let body = r#"{ "state": "Paused" }"#; - assert!(parse_patch_vm_state(&Body::new(body)) - .unwrap() - .eq(&ParsedRequest::new_sync(VmmAction::Pause))); + assert!( + parse_patch_vm_state(&Body::new(body)) + .unwrap() + .eq(&ParsedRequest::new_sync(VmmAction::Pause)) + ); let body = r#"{ "state": "Resumed" }"#; - assert!(parse_patch_vm_state(&Body::new(body)) - .unwrap() - .eq(&ParsedRequest::new_sync(VmmAction::Resume))); + assert!( + parse_patch_vm_state(&Body::new(body)) + .unwrap() + .eq(&ParsedRequest::new_sync(VmmAction::Resume)) + ); let invalid_body = r#"{ "invalid": "Paused" diff --git a/src/firecracker/src/api_server_adapter.rs b/src/firecracker/src/api_server_adapter.rs index 776d03a4daa..b6178a8cbf7 100644 --- a/src/firecracker/src/api_server_adapter.rs +++ b/src/firecracker/src/api_server_adapter.rs @@ -3,12 +3,12 @@ use std::os::unix::io::AsRawFd; use std::path::PathBuf; -use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError}; +use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel}; use std::sync::{Arc, Mutex}; use std::thread; use event_manager::{EventOps, Events, MutEventSubscriber, SubscriberOps}; -use vmm::logger::{error, warn, ProcessTimeReporter}; +use vmm::logger::{ProcessTimeReporter, error, warn}; use vmm::resources::VmResources; use vmm::rpc_interface::{ ApiRequest, ApiResponse, BuildMicrovmFromRequestsError, PrebootApiController, diff --git a/src/firecracker/src/main.rs b/src/firecracker/src/main.rs index 1433603a477..6b01f776729 100644 --- a/src/firecracker/src/main.rs +++ b/src/firecracker/src/main.rs @@ -22,7 +22,7 @@ use utils::validators::validate_instance_id; use vmm::arch::host_page_size; use vmm::builder::StartMicrovmError; use vmm::logger::{ - debug, error, info, LoggerConfig, ProcessTimeReporter, StoreMetric, LOGGER, METRICS, + LOGGER, LoggerConfig, METRICS, ProcessTimeReporter, StoreMetric, debug, error, info, }; use vmm::persist::SNAPSHOT_VERSION; use vmm::resources::VmResources; @@ -30,7 +30,7 @@ use vmm::seccomp::BpfThreadMap; use vmm::signal_handler::register_signal_handlers; use vmm::snapshot::{Snapshot, SnapshotError}; use vmm::vmm_config::instance_info::{InstanceInfo, VmState}; -use vmm::vmm_config::metrics::{init_metrics, MetricsConfig, MetricsConfigError}; +use vmm::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics}; use vmm::{EventManager, FcExitCode, HTTP_MAX_PAYLOAD_SIZE}; use vmm_sys_util::terminal::Terminal; diff --git a/src/firecracker/src/metrics.rs b/src/firecracker/src/metrics.rs index 9eaffd47811..80f21257107 100644 --- a/src/firecracker/src/metrics.rs +++ b/src/firecracker/src/metrics.rs @@ -6,7 +6,7 @@ use std::time::Duration; use event_manager::{EventOps, Events, MutEventSubscriber}; use timerfd::{ClockId, SetTimeFlags, TimerFd, TimerState}; -use vmm::logger::{error, warn, IncMetric, METRICS}; +use vmm::logger::{IncMetric, METRICS, error, warn}; use vmm_sys_util::epoll::EventSet; /// Metrics reporting period. diff --git a/src/firecracker/src/seccomp.rs b/src/firecracker/src/seccomp.rs index 2c7b3ddecd8..22069def685 100644 --- a/src/firecracker/src/seccomp.rs +++ b/src/firecracker/src/seccomp.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io::{BufReader, Read}; use std::path::Path; -use vmm::seccomp::{deserialize_binary, get_empty_filters, BpfThreadMap, DeserializationError}; +use vmm::seccomp::{BpfThreadMap, DeserializationError, deserialize_binary, get_empty_filters}; const THREAD_CATEGORIES: [&str; 3] = ["vmm", "api", "vcpu"]; diff --git a/src/jailer/src/cgroup.rs b/src/jailer/src/cgroup.rs index 1661b443a13..94098d3698f 100644 --- a/src/jailer/src/cgroup.rs +++ b/src/jailer/src/cgroup.rs @@ -11,7 +11,7 @@ use std::process; use regex::Regex; -use crate::{readln_special, writeln_special, JailerError}; +use crate::{JailerError, readln_special, writeln_special}; // Holds information on a cgroup mount point discovered on the system #[derive(Debug)] @@ -817,9 +817,11 @@ mod tests { ); // check that the controller was enabled in all parent dirs - assert!(read_first_line(cg_root.join("cgroup.subtree_control")) - .unwrap() - .contains("cpuset")); + assert!( + read_first_line(cg_root.join("cgroup.subtree_control")) + .unwrap() + .contains("cpuset") + ); assert!( read_first_line(cg_root.join("fc_test_cgv2/cgroup.subtree_control")) .unwrap() diff --git a/src/jailer/src/chroot.rs b/src/jailer/src/chroot.rs index cad575227f4..56335c03a74 100644 --- a/src/jailer/src/chroot.rs +++ b/src/jailer/src/chroot.rs @@ -8,7 +8,7 @@ use std::ptr::null; use vmm_sys_util::syscall::SyscallReturnCode; -use super::{to_cstring, JailerError}; +use super::{JailerError, to_cstring}; const OLD_ROOT_DIR: &CStr = c"old_root"; const ROOT_DIR: &CStr = c"/"; diff --git a/src/jailer/src/env.rs b/src/jailer/src/env.rs index 83421b6d5d4..e337ea95f90 100644 --- a/src/jailer/src/env.rs +++ b/src/jailer/src/env.rs @@ -2,24 +2,24 @@ // SPDX-License-Identifier: Apache-2.0 use std::ffi::{CStr, CString, OsString}; -use std::fs::{self, canonicalize, read_to_string, File, OpenOptions, Permissions}; +use std::fs::{self, File, OpenOptions, Permissions, canonicalize, read_to_string}; use std::io; use std::io::Write; use std::os::unix::fs::PermissionsExt; use std::os::unix::io::AsRawFd; use std::os::unix::process::CommandExt; use std::path::{Component, Path, PathBuf}; -use std::process::{exit, id, Command, Stdio}; +use std::process::{Command, Stdio, exit, id}; use utils::arg_parser::UtilsArgParserError::MissingValue; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; use utils::{arg_parser, validators}; use vmm_sys_util::syscall::SyscallReturnCode; +use crate::JailerError; use crate::cgroup::{CgroupConfiguration, CgroupConfigurationBuilder}; use crate::chroot::chroot; -use crate::resource_limits::{ResourceLimits, FSIZE_ARG, NO_FILE_ARG}; -use crate::JailerError; +use crate::resource_limits::{FSIZE_ARG, NO_FILE_ARG, ResourceLimits}; pub const PROC_MOUNTS: &str = "/proc/mounts"; diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs index 7c97b618d9e..721531e49ba 100644 --- a/src/jailer/src/main.rs +++ b/src/jailer/src/main.rs @@ -8,7 +8,7 @@ use std::{env as p_env, fs, io}; use env::PROC_MOUNTS; use utils::arg_parser::{ArgParser, Argument, UtilsArgParserError as ParsingError}; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; use utils::validators; use vmm_sys_util::syscall::SyscallReturnCode; diff --git a/src/log-instrument/examples/five.rs b/src/log-instrument/examples/five.rs index e43064c18b5..07aa0951935 100644 --- a/src/log-instrument/examples/five.rs +++ b/src/log-instrument/examples/five.rs @@ -3,7 +3,7 @@ #![warn(clippy::pedantic)] -use log::{debug, info, warn, LevelFilter}; +use log::{LevelFilter, debug, info, warn}; fn main() { env_logger::builder() diff --git a/src/seccompiler/src/bin.rs b/src/seccompiler/src/bin.rs index 8fb9d0fd511..749d04b570d 100644 --- a/src/seccompiler/src/bin.rs +++ b/src/seccompiler/src/bin.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use clap::Parser; -use seccompiler::{compile_bpf, CompilationError}; +use seccompiler::{CompilationError, compile_bpf}; const DEFAULT_OUTPUT_FILENAME: &str = "seccomp_binary_filter.out"; diff --git a/src/snapshot-editor/src/edit_vmstate.rs b/src/snapshot-editor/src/edit_vmstate.rs index 1d35cc19760..a96f84db6a0 100644 --- a/src/snapshot-editor/src/edit_vmstate.rs +++ b/src/snapshot-editor/src/edit_vmstate.rs @@ -8,7 +8,7 @@ use clap_num::maybe_hex; use vmm::arch::aarch64::regs::Aarch64RegisterVec; use vmm::persist::MicrovmState; -use crate::utils::{open_vmstate, save_vmstate, UtilsError}; +use crate::utils::{UtilsError, open_vmstate, save_vmstate}; #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum EditVmStateError { diff --git a/src/snapshot-editor/src/main.rs b/src/snapshot-editor/src/main.rs index cc940b341f4..fbc4a2ab883 100644 --- a/src/snapshot-editor/src/main.rs +++ b/src/snapshot-editor/src/main.rs @@ -9,10 +9,10 @@ mod edit_vmstate; mod info; mod utils; -use edit_memory::{edit_memory_command, EditMemoryError, EditMemorySubCommand}; +use edit_memory::{EditMemoryError, EditMemorySubCommand, edit_memory_command}; #[cfg(target_arch = "aarch64")] -use edit_vmstate::{edit_vmstate_command, EditVmStateError, EditVmStateSubCommand}; -use info::{info_vmstate_command, InfoVmStateError, InfoVmStateSubCommand}; +use edit_vmstate::{EditVmStateError, EditVmStateSubCommand, edit_vmstate_command}; +use info::{InfoVmStateError, InfoVmStateSubCommand, info_vmstate_command}; #[derive(Debug, thiserror::Error, displaydoc::Display)] enum SnapEditorError { diff --git a/src/utils/src/arg_parser.rs b/src/utils/src/arg_parser.rs index 47dfe3a88a4..e76d38b7609 100644 --- a/src/utils/src/arg_parser.rs +++ b/src/utils/src/arg_parser.rs @@ -438,7 +438,7 @@ impl<'a> Arguments<'a> { _ => { return Err(UtilsArgParserError::UnexpectedArgument( argument.name.to_string(), - )) + )); } } } else { diff --git a/src/vmm/benches/block_request.rs b/src/vmm/benches/block_request.rs index a616a48b5bf..1ccf3e7c3b6 100644 --- a/src/vmm/benches/block_request.rs +++ b/src/vmm/benches/block_request.rs @@ -6,7 +6,7 @@ // * `Queue.add_used` // * `DescriptorChain.next_descriptor` -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{Criterion, criterion_group, criterion_main}; use vm_memory::GuestAddress; use vmm::devices::virtio::block::virtio::test_utils::RequestDescriptorChain; use vmm::devices::virtio::block::virtio::{Request, RequestHeader, VIRTIO_BLK_T_IN}; diff --git a/src/vmm/benches/cpu_templates.rs b/src/vmm/benches/cpu_templates.rs index 75060a58675..e31ad7261aa 100644 --- a/src/vmm/benches/cpu_templates.rs +++ b/src/vmm/benches/cpu_templates.rs @@ -7,9 +7,9 @@ use std::mem::size_of_val; -use criterion::{criterion_group, criterion_main, Criterion}; -use vmm::cpu_config::templates::test_utils::{build_test_template, TEST_TEMPLATE_JSON}; +use criterion::{Criterion, criterion_group, criterion_main}; use vmm::cpu_config::templates::CustomCpuTemplate; +use vmm::cpu_config::templates::test_utils::{TEST_TEMPLATE_JSON, build_test_template}; #[inline] pub fn bench_serialize_cpu_template(cpu_template: &CustomCpuTemplate) { diff --git a/src/vmm/benches/memory_access.rs b/src/vmm/benches/memory_access.rs index 2a9f7974108..4dfb9dc9213 100644 --- a/src/vmm/benches/memory_access.rs +++ b/src/vmm/benches/memory_access.rs @@ -1,7 +1,7 @@ // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; use vm_memory::GuestMemory; use vmm::resources::VmResources; use vmm::vmm_config::machine_config::{HugePageConfig, MachineConfig}; diff --git a/src/vmm/benches/queue.rs b/src/vmm/benches/queue.rs index 1d19bcd3973..b5536fa7ef1 100644 --- a/src/vmm/benches/queue.rs +++ b/src/vmm/benches/queue.rs @@ -8,7 +8,7 @@ use std::num::Wrapping; -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{Criterion, criterion_group, criterion_main}; use vm_memory::GuestAddress; use vmm::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; use vmm::devices::virtio::test_utils::VirtQueue; diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index e89d259ed3a..59bca9eadfd 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use acpi_tables::fadt::{FADT_F_HW_REDUCED_ACPI, FADT_F_PWR_BUTTON, FADT_F_SLP_BUTTON}; -use acpi_tables::{aml, Aml, Dsdt, Fadt, Madt, Rsdp, Sdt, Xsdt}; +use acpi_tables::{Aml, Dsdt, Fadt, Madt, Rsdp, Sdt, Xsdt, aml}; use log::{debug, error}; use vm_allocator::AllocPolicy; +use crate::Vcpu; use crate::acpi::x86_64::{ apic_addr, rsdp_addr, setup_arch_dsdt, setup_arch_fadt, setup_interrupt_controllers, }; @@ -13,7 +14,6 @@ use crate::device_manager::acpi::ACPIDeviceManager; use crate::device_manager::mmio::MMIODeviceManager; use crate::device_manager::resources::ResourceAllocator; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; -use crate::Vcpu; mod x86_64; diff --git a/src/vmm/src/acpi/x86_64.rs b/src/vmm/src/acpi/x86_64.rs index d7328aecba9..de850a9989f 100644 --- a/src/vmm/src/acpi/x86_64.rs +++ b/src/vmm/src/acpi/x86_64.rs @@ -8,7 +8,7 @@ use acpi_tables::fadt::{ IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT, }; use acpi_tables::madt::{IoAPIC, LocalAPIC}; -use acpi_tables::{aml, Fadt}; +use acpi_tables::{Fadt, aml}; use vm_memory::GuestAddress; use zerocopy::IntoBytes; diff --git a/src/vmm/src/arch/aarch64/cache_info.rs b/src/vmm/src/arch/aarch64/cache_info.rs index fd7d6e0a2ea..8f8611fe440 100644 --- a/src/vmm/src/arch/aarch64/cache_info.rs +++ b/src/vmm/src/arch/aarch64/cache_info.rs @@ -320,7 +320,7 @@ mod tests { use super::*; use crate::arch::aarch64::cache_info::{ - read_cache_config, CacheEngine, CacheEntry, CacheStore, + CacheEngine, CacheEntry, CacheStore, read_cache_config, }; #[derive(Debug)] diff --git a/src/vmm/src/arch/aarch64/fdt.rs b/src/vmm/src/arch/aarch64/fdt.rs index ff8c561910a..2eb154a33b3 100644 --- a/src/vmm/src/arch/aarch64/fdt.rs +++ b/src/vmm/src/arch/aarch64/fdt.rs @@ -13,9 +13,9 @@ use vm_fdt::{Error as VmFdtError, FdtWriter, FdtWriterNode}; use vm_memory::GuestMemoryError; use super::super::{DeviceType, InitrdConfig}; -use super::cache_info::{read_cache_config, CacheEntry}; +use super::cache_info::{CacheEntry, read_cache_config}; use super::gic::GICDevice; -use crate::devices::acpi::vmgenid::{VmGenId, VMGENID_MEM_SIZE}; +use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId}; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap}; // This is a value for uniquely identifying the FDT node declaring the interrupt controller. diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs index a4179e895ae..21a404b302b 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/dist_regs.rs @@ -6,8 +6,8 @@ use std::ops::Range; use kvm_bindings::KVM_DEV_ARM_VGIC_GRP_DIST_REGS; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{GicRegState, MmioReg, SimpleReg, VgicRegEngine}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{GicRegState, MmioReg, SimpleReg, VgicRegEngine}; use crate::arch::{IRQ_BASE, IRQ_MAX}; // Distributor registers as detailed at page 75 from @@ -133,7 +133,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion, GicError}; + use crate::arch::aarch64::gic::{GICVersion, GicError, create_gic}; #[test] fn test_access_dist_regs() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs index be963a8327e..d50b74a5fb4 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/icc_regs.rs @@ -4,8 +4,8 @@ use kvm_bindings::*; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{SimpleReg, VgicRegEngine, VgicSysRegsState}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{SimpleReg, VgicRegEngine, VgicSysRegsState}; // CPU interface registers as detailed at page 76 from // https://developer.arm.com/documentation/ihi0048/latest/. @@ -86,7 +86,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion, GicError}; + use crate::arch::aarch64::gic::{GICVersion, GicError, create_gic}; #[test] fn test_access_icc_regs() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs index a0c0e2c8fac..8bb26ce2bcd 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv2/regs/mod.rs @@ -6,8 +6,8 @@ mod icc_regs; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{GicState, GicVcpuState}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{GicState, GicVcpuState}; /// Save the state of the GIC device. pub fn save_state(fd: &DeviceFd, mpidrs: &[u64]) -> Result { @@ -46,7 +46,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_vm_save_restore_state() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs index 50d2e5130db..558b47ab065 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/mod.rs @@ -202,7 +202,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_save_pending_tables() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs index 5af3e9215c0..96c617dcc17 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/dist_regs.rs @@ -6,8 +6,8 @@ use std::ops::Range; use kvm_bindings::KVM_DEV_ARM_VGIC_GRP_DIST_REGS; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{GicRegState, MmioReg, SimpleReg, VgicRegEngine}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{GicRegState, MmioReg, SimpleReg, VgicRegEngine}; use crate::arch::{IRQ_BASE, IRQ_MAX}; // Distributor registers as detailed at page 456 from @@ -134,7 +134,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_access_dist_regs() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs index d242bce8433..f79430e9a13 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/icc_regs.rs @@ -4,8 +4,8 @@ use kvm_bindings::*; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{SimpleReg, VgicRegEngine, VgicSysRegsState}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{SimpleReg, VgicRegEngine, VgicSysRegsState}; const ICC_CTLR_EL1_PRIBITS_SHIFT: u64 = 8; const ICC_CTLR_EL1_PRIBITS_MASK: u64 = 7 << ICC_CTLR_EL1_PRIBITS_SHIFT; @@ -170,7 +170,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_access_icc_regs() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs index 31261f647fc..0531766dc54 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/mod.rs @@ -7,8 +7,8 @@ mod redist_regs; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{GicState, GicVcpuState}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{GicState, GicVcpuState}; /// Save the state of the GIC device. pub fn save_state(fd: &DeviceFd, mpidrs: &[u64]) -> Result { @@ -51,7 +51,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_vm_save_restore_state() { diff --git a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs index 88af82e3cb2..4d1ba3292c1 100644 --- a/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs +++ b/src/vmm/src/arch/aarch64/gic/gicv3/regs/redist_regs.rs @@ -4,8 +4,8 @@ use kvm_bindings::*; use kvm_ioctls::DeviceFd; -use crate::arch::aarch64::gic::regs::{GicRegState, SimpleReg, VgicRegEngine}; use crate::arch::aarch64::gic::GicError; +use crate::arch::aarch64::gic::regs::{GicRegState, SimpleReg, VgicRegEngine}; // Relevant PPI redistributor registers that we want to save/restore. const GICR_CTLR: SimpleReg = SimpleReg::new(0x0000, 4); @@ -91,7 +91,7 @@ mod tests { use kvm_ioctls::Kvm; use super::*; - use crate::arch::aarch64::gic::{create_gic, GICVersion}; + use crate::arch::aarch64::gic::{GICVersion, create_gic}; #[test] fn test_access_redist_regs() { diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 8fa7c2463bf..41530737089 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -14,9 +14,9 @@ pub mod aarch64; #[cfg(target_arch = "aarch64")] pub use aarch64::{ - arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr, - layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, - layout::SYSTEM_MEM_START, ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, + ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, + get_kernel_start, initrd_load_addr, layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, + layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, }; /// Module for x86_64 related functionality. @@ -25,10 +25,10 @@ pub mod x86_64; #[cfg(target_arch = "x86_64")] pub use crate::arch::x86_64::{ - arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr, layout::APIC_ADDR, - layout::CMDLINE_MAX_SIZE, layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, - layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, ConfigurationError, MMIO_MEM_SIZE, - MMIO_MEM_START, + ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, + get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::CMDLINE_MAX_SIZE, + layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, + layout::SYSTEM_MEM_START, }; /// Types of devices that can get attached to this platform. diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index a0f6d98889d..f10fd3446d8 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -502,12 +502,14 @@ mod tests { // Exercise the scenario where the field storing the length of the e820 entry table is // is bigger than the allocated memory. params.e820_entries = u8::try_from(params.e820_table.len()).unwrap() + 1; - assert!(add_e820_entry( - &mut params, - e820_map[0].addr, - e820_map[0].size, - e820_map[0].type_ - ) - .is_err()); + assert!( + add_e820_entry( + &mut params, + e820_map[0].addr, + e820_map[0].size, + e820_map[0].type_ + ) + .is_err() + ); } } diff --git a/src/vmm/src/arch/x86_64/mptable.rs b/src/vmm/src/arch/x86_64/mptable.rs index ce93555ad7e..6646c17e282 100644 --- a/src/vmm/src/arch/x86_64/mptable.rs +++ b/src/vmm/src/arch/x86_64/mptable.rs @@ -13,8 +13,8 @@ use libc::c_char; use log::debug; use vm_allocator::AllocPolicy; -use crate::arch::x86_64::generated::mpspec; use crate::arch::IRQ_MAX; +use crate::arch::x86_64::generated::mpspec; use crate::device_manager::resources::ResourceAllocator; use crate::vstate::memory::{ Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, diff --git a/src/vmm/src/arch/x86_64/msr.rs b/src/vmm/src/arch/x86_64/msr.rs index 2142eba5aa5..f8674c6c3a5 100644 --- a/src/vmm/src/arch/x86_64/msr.rs +++ b/src/vmm/src/arch/x86_64/msr.rs @@ -3,7 +3,7 @@ /// Model Specific Registers (MSRs) related functionality. use bitflags::bitflags; -use kvm_bindings::{kvm_msr_entry, MsrList, Msrs}; +use kvm_bindings::{MsrList, Msrs, kvm_msr_entry}; use kvm_ioctls::{Kvm, VcpuFd}; use crate::arch::x86_64::generated::hyperv::*; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index bd956cb2b47..499d64cae6c 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -14,13 +14,13 @@ use std::sync::{Arc, Mutex}; use event_manager::{MutEventSubscriber, SubscriberOps}; use libc::EFD_NONBLOCK; use linux_loader::cmdline::Cmdline as LoaderKernelCmdline; +use linux_loader::loader::KernelLoader; #[cfg(target_arch = "x86_64")] use linux_loader::loader::elf::Elf as Loader; #[cfg(target_arch = "x86_64")] use linux_loader::loader::elf::PvhBootCapability; #[cfg(target_arch = "aarch64")] use linux_loader::loader::pe::PE as Loader; -use linux_loader::loader::KernelLoader; use userfaultfd::Uffd; use utils::time::TimestampUs; use vm_memory::ReadVolatile; @@ -46,10 +46,11 @@ use crate::device_manager::persist::{ ACPIDeviceManagerConstructorArgs, ACPIDeviceManagerRestoreError, MMIODevManagerConstructorArgs, }; use crate::device_manager::resources::ResourceAllocator; +use crate::devices::BusDevice; use crate::devices::acpi::vmgenid::{VmGenId, VmGenIdError}; -use crate::devices::legacy::serial::SerialOut; #[cfg(target_arch = "aarch64")] use crate::devices::legacy::RTCDevice; +use crate::devices::legacy::serial::SerialOut; use crate::devices::legacy::{EventFdTrigger, SerialEventsWrapper, SerialWrapper}; use crate::devices::virtio::balloon::Balloon; use crate::devices::virtio::block::device::Block; @@ -58,7 +59,6 @@ use crate::devices::virtio::mmio::MmioTransport; use crate::devices::virtio::net::Net; use crate::devices::virtio::rng::Entropy; use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend}; -use crate::devices::BusDevice; #[cfg(feature = "gdb")] use crate::gdb; use crate::logger::{debug, error}; @@ -74,7 +74,7 @@ use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; use crate::vstate::vm::Vm; -use crate::{device_manager, EventManager, Vmm, VmmError}; +use crate::{EventManager, Vmm, VmmError, device_manager}; /// Errors associated with starting the instance. #[derive(Debug, thiserror::Error, displaydoc::Display)] @@ -663,7 +663,7 @@ where return Err(InitrdRead(io::Error::new( io::ErrorKind::InvalidData, "Initrd image seek returned a size of zero", - ))) + ))); } Ok(s) => size = u64_to_usize(s), }; @@ -961,9 +961,7 @@ fn attach_block_devices<'a, I: Iterator>> + Debug>( let locked = block.lock().expect("Poisoned lock"); if locked.root_device() { match locked.partuuid() { - Some(partuuid) => { - cmdline.insert_str(format!("root=PARTUUID={}", partuuid))? - } + Some(partuuid) => cmdline.insert_str(format!("root=PARTUUID={}", partuuid))?, None => cmdline.insert_str("root=/dev/vda")?, } match locked.read_only() { @@ -1053,7 +1051,7 @@ pub(crate) mod tests { use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; use crate::test_utils::{single_region_mem, single_region_mem_at}; - use crate::vmm_config::balloon::{BalloonBuilder, BalloonDeviceConfig, BALLOON_DEV_ID}; + use crate::vmm_config::balloon::{BALLOON_DEV_ID, BalloonBuilder, BalloonDeviceConfig}; use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE; use crate::vmm_config::drive::{BlockBuilder, BlockDeviceConfig}; use crate::vmm_config::entropy::{EntropyDeviceBuilder, EntropyDeviceConfig}; @@ -1247,10 +1245,11 @@ pub(crate) mod tests { attach_unixsock_vsock_device(vmm, cmdline, &vsock, event_manager).unwrap(); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_VSOCK), &vsock_dev_id) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_VSOCK), &vsock_dev_id) + .is_some() + ); } pub(crate) fn insert_entropy_device( @@ -1264,10 +1263,11 @@ pub(crate) mod tests { attach_entropy_device(vmm, cmdline, &entropy, event_manager).unwrap(); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_RNG), ENTROPY_DEV_ID) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_RNG), ENTROPY_DEV_ID) + .is_some() + ); } #[cfg(target_arch = "x86_64")] @@ -1288,10 +1288,11 @@ pub(crate) mod tests { attach_balloon_device(vmm, cmdline, balloon, event_manager).unwrap(); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BALLOON), BALLOON_DEV_ID) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BALLOON), BALLOON_DEV_ID) + .is_some() + ); } fn make_test_bin() -> Vec { @@ -1399,10 +1400,11 @@ pub(crate) mod tests { let mut cmdline = default_kernel_cmdline(); insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=/dev/vda ro")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } // Use case 2: root block device is specified through PARTUUID. @@ -1419,10 +1421,11 @@ pub(crate) mod tests { let mut cmdline = default_kernel_cmdline(); insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 rw")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } // Use case 3: root block device is not added at all. @@ -1440,10 +1443,11 @@ pub(crate) mod tests { insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(!cmdline_contains(&cmdline, "root=PARTUUID=")); assert!(!cmdline_contains(&cmdline, "root=/dev/vda")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } // Use case 4: rw root block device and other rw and ro drives. @@ -1476,18 +1480,21 @@ pub(crate) mod tests { insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 rw")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), "root") - .is_some()); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), "secondary") - .is_some()); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), "third") - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), "root") + .is_some() + ); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), "secondary") + .is_some() + ); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), "third") + .is_some() + ); // Check if these three block devices are inserted in kernel_cmdline. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -1512,10 +1519,11 @@ pub(crate) mod tests { let mut cmdline = default_kernel_cmdline(); insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=/dev/vda rw")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } // Use case 6: root block device is ro, with PARTUUID. @@ -1532,10 +1540,11 @@ pub(crate) mod tests { let mut cmdline = default_kernel_cmdline(); insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=PARTUUID=0eaa91a0-01 ro")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } // Use case 7: root block device is rw with flush enabled @@ -1552,10 +1561,11 @@ pub(crate) mod tests { let mut cmdline = default_kernel_cmdline(); insert_block_devices(&mut vmm, &mut cmdline, &mut event_manager, block_configs); assert!(cmdline_contains(&cmdline, "root=/dev/vda rw")); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::Virtio(TYPE_BLOCK), drive_id.as_str()) + .is_some() + ); } } @@ -1566,10 +1576,11 @@ pub(crate) mod tests { let res = attach_boot_timer_device(&mut vmm, request_ts); res.unwrap(); - assert!(vmm - .mmio_device_manager - .get_device(DeviceType::BootTimer, &DeviceType::BootTimer.to_string()) - .is_some()); + assert!( + vmm.mmio_device_manager + .get_device(DeviceType::BootTimer, &DeviceType::BootTimer.to_string()) + .is_some() + ); } #[test] 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 8c51916bafc..2869f28ff4a 100644 --- a/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs +++ b/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use serde::de::Error; use serde::{Deserialize, Serialize}; -use crate::arch::aarch64::regs::{reg_size, RegSize}; +use crate::arch::aarch64::regs::{RegSize, reg_size}; use crate::cpu_config::aarch64::static_cpu_templates::v1n1; use crate::cpu_config::templates::{ CpuTemplateType, GetCpuTemplate, GetCpuTemplateError, KvmCapability, RegisterValueFilter, @@ -79,7 +79,7 @@ impl CustomCpuTemplate { "Invalid aarch64 register address: {:#x} - Only 32, 64 and 128 bit wide \ registers are supported", modifier.addr - ))) + ))); } } } @@ -116,7 +116,7 @@ mod tests { use serde_json::Value; use super::*; - use crate::cpu_config::templates::test_utils::{build_test_template, TEST_TEMPLATE_JSON}; + use crate::cpu_config::templates::test_utils::{TEST_TEMPLATE_JSON, build_test_template}; #[test] fn test_get_cpu_template_with_no_template() { @@ -231,10 +231,12 @@ mod tests { ] }"#, ); - assert!(cpu_config_result - .unwrap_err() - .to_string() - .contains("Failed to parse string [0bK] as a number for CPU template")); + assert!( + cpu_config_result + .unwrap_err() + .to_string() + .contains("Failed to parse string [0bK] as a number for CPU template") + ); // Malformed 64-bit bitmap - filter failed let cpu_config_result = serde_json::from_str::( @@ -262,10 +264,11 @@ mod tests { ] }"#, ); - assert!(cpu_config_result - .unwrap_err() - .to_string() - .contains("Failed to parse string [0bx00100x0x1xxxx05xxx1xxxxxxxxxxx1] as a bitmap")); + assert!( + cpu_config_result.unwrap_err().to_string().contains( + "Failed to parse string [0bx00100x0x1xxxx05xxx1xxxxxxxxxxx1] as a bitmap" + ) + ); } #[test] diff --git a/src/vmm/src/cpu_config/templates.rs b/src/vmm/src/cpu_config/templates.rs index fa883964ed8..559da632cc4 100644 --- a/src/vmm/src/cpu_config/templates.rs +++ b/src/vmm/src/cpu_config/templates.rs @@ -6,7 +6,7 @@ mod common_types { pub use crate::cpu_config::x86_64::custom_cpu_template::CustomCpuTemplate; pub use crate::cpu_config::x86_64::static_cpu_templates::StaticCpuTemplate; pub use crate::cpu_config::x86_64::{ - test_utils, CpuConfiguration, CpuConfigurationError as GuestConfigError, + CpuConfiguration, CpuConfigurationError as GuestConfigError, test_utils, }; } @@ -15,7 +15,7 @@ mod common_types { pub use crate::cpu_config::aarch64::custom_cpu_template::CustomCpuTemplate; pub use crate::cpu_config::aarch64::static_cpu_templates::StaticCpuTemplate; pub use crate::cpu_config::aarch64::{ - test_utils, CpuConfiguration, CpuConfigurationError as GuestConfigError, + CpuConfiguration, CpuConfigurationError as GuestConfigError, test_utils, }; } @@ -250,7 +250,7 @@ where return Err(D::Error::custom(format!( "Failed to parse string [{}] as a bitmap - unknown character: {}", original_str, c - ))) + ))); } } i += 1; diff --git a/src/vmm/src/cpu_config/templates_serde.rs b/src/vmm/src/cpu_config/templates_serde.rs index 11eb6062853..91bb37b29dc 100644 --- a/src/vmm/src/cpu_config/templates_serde.rs +++ b/src/vmm/src/cpu_config/templates_serde.rs @@ -51,8 +51,8 @@ deserialize_from_str!(deserialize_from_str_u64, u64); #[cfg(test)] mod tests { - use serde::de::value::{Error, StrDeserializer}; use serde::de::IntoDeserializer; + use serde::de::value::{Error, StrDeserializer}; use super::*; diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs index f2f46b54c3d..111960db00a 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs @@ -1,13 +1,13 @@ // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use crate::cpu_config::x86_64::cpuid::common::{get_vendor_id_from_host, GetCpuidError}; +use crate::cpu_config::x86_64::cpuid::common::{GetCpuidError, get_vendor_id_from_host}; use crate::cpu_config::x86_64::cpuid::normalize::{ - get_range, set_bit, set_range, CheckedAssignError, + CheckedAssignError, get_range, set_bit, set_range, }; use crate::cpu_config::x86_64::cpuid::{ - cpuid, cpuid_count, CpuidEntry, CpuidKey, CpuidRegisters, CpuidTrait, KvmCpuidFlags, - MissingBrandStringLeaves, BRAND_STRING_LENGTH, VENDOR_ID_AMD, + BRAND_STRING_LENGTH, CpuidEntry, CpuidKey, CpuidRegisters, CpuidTrait, KvmCpuidFlags, + MissingBrandStringLeaves, VENDOR_ID_AMD, cpuid, cpuid_count, }; /// Error type for [`super::AmdCpuid::normalize`]. diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 74536e44241..41bc9d3f3f5 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::cpu_config::x86_64::cpuid::normalize::{ - get_range, set_bit, set_range, CheckedAssignError, + CheckedAssignError, get_range, set_bit, set_range, }; use crate::cpu_config::x86_64::cpuid::{ - host_brand_string, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves, - BRAND_STRING_LENGTH, + BRAND_STRING_LENGTH, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves, + host_brand_string, }; /// Error type for [`super::IntelCpuid::normalize`]. diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/mod.rs b/src/vmm/src/cpu_config/x86_64/cpuid/mod.rs index 2350d30479d..41a5409799a 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/mod.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/mod.rs @@ -720,12 +720,14 @@ mod tests { }), None ); - assert!(cpuid - .get(&CpuidKey { - leaf: 0x0, - subleaf: 0x0, - }) - .is_some()); + assert!( + cpuid + .get(&CpuidKey { + leaf: 0x0, + subleaf: 0x0, + }) + .is_some() + ); } #[test] @@ -738,12 +740,14 @@ mod tests { }), None ); - assert!(cpuid - .get_mut(&CpuidKey { - leaf: 0x0, - subleaf: 0x0, - }) - .is_some()); + assert!( + cpuid + .get_mut(&CpuidKey { + leaf: 0x0, + subleaf: 0x0, + }) + .is_some() + ); } #[test] diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index 2ac00b23a54..cec8aad2f4c 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::cpu_config::x86_64::cpuid::{ - cpuid, CpuidEntry, CpuidKey, CpuidRegisters, CpuidTrait, KvmCpuidFlags, + CpuidEntry, CpuidKey, CpuidRegisters, CpuidTrait, KvmCpuidFlags, cpuid, }; /// Error type for [`super::Cpuid::normalize`]. 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 0443d997ead..15ba76abbe4 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 @@ -15,7 +15,7 @@ use crate::cpu_config::templates::{ use crate::cpu_config::templates_serde::*; use crate::cpu_config::x86_64::cpuid::common::get_vendor_id_from_host; use crate::cpu_config::x86_64::cpuid::{KvmCpuidFlags, VENDOR_ID_AMD, VENDOR_ID_INTEL}; -use crate::cpu_config::x86_64::static_cpu_templates::{c3, t2, t2a, t2cl, t2s, StaticCpuTemplate}; +use crate::cpu_config::x86_64::static_cpu_templates::{StaticCpuTemplate, c3, t2, t2a, t2cl, t2s}; use crate::logger::warn; impl GetCpuTemplate for Option { @@ -192,7 +192,7 @@ where _ => { return Err(D::Error::custom( "Invalid CPUID register. Must be one of [eax, ebx, ecx, edx]", - )) + )); } }) } @@ -214,7 +214,7 @@ mod tests { use serde_json::Value; use super::*; - use crate::cpu_config::x86_64::test_utils::{build_test_template, TEST_TEMPLATE_JSON}; + use crate::cpu_config::x86_64::test_utils::{TEST_TEMPLATE_JSON, build_test_template}; #[test] fn test_get_cpu_template_with_no_template() { @@ -386,10 +386,12 @@ mod tests { ], }"#, ); - assert!(cpu_template_result - .unwrap_err() - .to_string() - .contains("Invalid CPUID register. Must be one of [eax, ebx, ecx, edx]")); + assert!( + cpu_template_result + .unwrap_err() + .to_string() + .contains("Invalid CPUID register. Must be one of [eax, ebx, ecx, edx]") + ); // Malformed MSR register address let cpu_template_result = serde_json::from_str::( @@ -460,10 +462,11 @@ mod tests { ] }"#, ); - assert!(cpu_template_result - .unwrap_err() - .to_string() - .contains("Failed to parse string [0bx00100x0x1xxxx05xxx1xxxxxxxxxxx1] as a bitmap")); + assert!( + cpu_template_result.unwrap_err().to_string().contains( + "Failed to parse string [0bx00100x0x1xxxx05xxx1xxxxxxxxxxx1] as a bitmap" + ) + ); } #[test] diff --git a/src/vmm/src/device_manager/acpi.rs b/src/vmm/src/device_manager/acpi.rs index 03315cbcc3c..78f1254d2fa 100644 --- a/src/vmm/src/device_manager/acpi.rs +++ b/src/vmm/src/device_manager/acpi.rs @@ -1,7 +1,7 @@ // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use acpi_tables::{aml, Aml}; +use acpi_tables::{Aml, aml}; use kvm_ioctls::VmFd; use crate::devices::acpi::vmgenid::VmGenId; diff --git a/src/vmm/src/device_manager/legacy.rs b/src/vmm/src/device_manager/legacy.rs index eee2f86dc83..7ced10dbbe5 100644 --- a/src/vmm/src/device_manager/legacy.rs +++ b/src/vmm/src/device_manager/legacy.rs @@ -10,7 +10,7 @@ use std::fmt::Debug; use std::sync::{Arc, Mutex}; use acpi_tables::aml::AmlError; -use acpi_tables::{aml, Aml}; +use acpi_tables::{Aml, aml}; use kvm_ioctls::VmFd; use libc::EFD_NONBLOCK; use vm_superio::Serial; diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index dc814de9766..b4961623a15 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -11,7 +11,7 @@ use std::num::NonZeroU32; use std::sync::{Arc, Mutex}; #[cfg(target_arch = "x86_64")] -use acpi_tables::{aml, Aml}; +use acpi_tables::{Aml, aml}; use kvm_ioctls::{IoEventAddress, VmFd}; use linux_loader::cmdline as kernel_cmdline; #[cfg(target_arch = "x86_64")] @@ -21,11 +21,12 @@ use serde::{Deserialize, Serialize}; use vm_allocator::AllocPolicy; use super::resources::ResourceAllocator; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::DeviceInfoForFDT; use crate::arch::DeviceType; use crate::arch::DeviceType::Virtio; #[cfg(target_arch = "aarch64")] +use crate::arch::aarch64::DeviceInfoForFDT; +use crate::devices::BusDevice; +#[cfg(target_arch = "aarch64")] use crate::devices::legacy::RTCDevice; use crate::devices::pseudo::BootTimer; use crate::devices::virtio::balloon::Balloon; @@ -34,9 +35,8 @@ use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::mmio::MmioTransport; use crate::devices::virtio::net::Net; use crate::devices::virtio::rng::Entropy; -use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend, TYPE_VSOCK}; +use crate::devices::virtio::vsock::{TYPE_VSOCK, Vsock, VsockUnixBackend}; use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_NET, TYPE_RNG}; -use crate::devices::BusDevice; #[cfg(target_arch = "x86_64")] use crate::vstate::memory::GuestAddress; @@ -543,13 +543,13 @@ mod tests { use vmm_sys_util::eventfd::EventFd; use super::*; + use crate::Vm; + use crate::devices::virtio::ActivateError; use crate::devices::virtio::device::{IrqTrigger, VirtioDevice}; use crate::devices::virtio::queue::Queue; - use crate::devices::virtio::ActivateError; use crate::test_utils::multi_region_mem; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; - use crate::Vm; const QUEUE_SIZES: &[u16] = &[64]; @@ -780,9 +780,11 @@ mod tests { &id, ) .unwrap(); - assert!(device_manager - .get_device(DeviceType::Virtio(type_id), &id) - .is_some()); + assert!( + device_manager + .get_device(DeviceType::Virtio(type_id), &id) + .is_some() + ); assert_eq!( addr, device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id.clone())].addr @@ -796,9 +798,11 @@ mod tests { ); let id = "bar"; - assert!(device_manager - .get_device(DeviceType::Virtio(type_id), id) - .is_none()); + assert!( + device_manager + .get_device(DeviceType::Virtio(type_id), id) + .is_none() + ); let dummy2 = Arc::new(Mutex::new(DummyDevice::new())); let id2 = String::from("foo2"); diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index bdf63409d68..ffab7b81bfd 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -15,30 +15,31 @@ use vm_allocator::AllocPolicy; use super::acpi::ACPIDeviceManager; use super::mmio::*; use super::resources::ResourceAllocator; +use crate::EventManager; #[cfg(target_arch = "aarch64")] use crate::arch::DeviceType; use crate::devices::acpi::vmgenid::{VMGenIDState, VMGenIdConstructorArgs, VmGenId, VmGenIdError}; use crate::devices::virtio::balloon::persist::{BalloonConstructorArgs, BalloonState}; use crate::devices::virtio::balloon::{Balloon, BalloonError}; +use crate::devices::virtio::block::BlockError; use crate::devices::virtio::block::device::Block; use crate::devices::virtio::block::persist::{BlockConstructorArgs, BlockState}; -use crate::devices::virtio::block::BlockError; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::mmio::MmioTransport; +use crate::devices::virtio::net::Net; use crate::devices::virtio::net::persist::{ NetConstructorArgs, NetPersistError as NetError, NetState, }; -use crate::devices::virtio::net::Net; use crate::devices::virtio::persist::{MmioTransportConstructorArgs, MmioTransportState}; +use crate::devices::virtio::rng::Entropy; use crate::devices::virtio::rng::persist::{ EntropyConstructorArgs, EntropyPersistError as EntropyError, EntropyState, }; -use crate::devices::virtio::rng::Entropy; use crate::devices::virtio::vsock::persist::{ VsockConstructorArgs, VsockState, VsockUdsConstructorArgs, }; use crate::devices::virtio::vsock::{ - Vsock, VsockError, VsockUnixBackend, VsockUnixBackendError, TYPE_VSOCK, + TYPE_VSOCK, Vsock, VsockError, VsockUnixBackend, VsockUnixBackendError, }; use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_NET, TYPE_RNG}; use crate::mmds::data_store::MmdsVersion; @@ -46,7 +47,6 @@ use crate::resources::{ResourcesError, VmResources}; use crate::snapshot::Persist; use crate::vmm_config::mmds::MmdsConfigError; use crate::vstate::memory::GuestMemoryMmap; -use crate::EventManager; /// Errors for (de)serialization of the MMIO device manager. #[derive(Debug, thiserror::Error, displaydoc::Display)] diff --git a/src/vmm/src/devices/acpi/vmgenid.rs b/src/vmm/src/devices/acpi/vmgenid.rs index 13dd19902df..31dbf64ec39 100644 --- a/src/vmm/src/devices/acpi/vmgenid.rs +++ b/src/vmm/src/devices/acpi/vmgenid.rs @@ -1,7 +1,7 @@ // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use acpi_tables::{aml, Aml}; +use acpi_tables::{Aml, aml}; use aws_lc_rs::error::Unspecified as RandError; use aws_lc_rs::rand; use log::{debug, error}; diff --git a/src/vmm/src/devices/legacy/i8042.rs b/src/vmm/src/devices/legacy/i8042.rs index 8f965cab912..bcf7bdd8c90 100644 --- a/src/vmm/src/devices/legacy/i8042.rs +++ b/src/vmm/src/devices/legacy/i8042.rs @@ -12,7 +12,7 @@ use log::warn; use serde::Serialize; use vmm_sys_util::eventfd::EventFd; -use crate::logger::{error, IncMetric, SharedIncMetric}; +use crate::logger::{IncMetric, SharedIncMetric, error}; /// Errors thrown by the i8042 device. #[derive(Debug, thiserror::Error, displaydoc::Display)] diff --git a/src/vmm/src/devices/legacy/mod.rs b/src/vmm/src/devices/legacy/mod.rs index 25f332b9617..b28ae7082fe 100644 --- a/src/vmm/src/devices/legacy/mod.rs +++ b/src/vmm/src/devices/legacy/mod.rs @@ -14,8 +14,8 @@ pub mod serial; use std::io; use std::ops::Deref; -use serde::ser::SerializeMap; use serde::Serializer; +use serde::ser::SerializeMap; use vm_superio::Trigger; use vmm_sys_util::eventfd::EventFd; @@ -23,7 +23,7 @@ pub use self::i8042::{I8042Device, I8042Error as I8042DeviceError}; #[cfg(target_arch = "aarch64")] pub use self::rtc_pl031::RTCDevice; pub use self::serial::{ - SerialDevice, SerialEventsWrapper, SerialWrapper, IER_RDA_BIT, IER_RDA_OFFSET, + IER_RDA_BIT, IER_RDA_OFFSET, SerialDevice, SerialEventsWrapper, SerialWrapper, }; /// Wrapper for implementing the trigger functionality for `EventFd`. diff --git a/src/vmm/src/devices/legacy/rtc_pl031.rs b/src/vmm/src/devices/legacy/rtc_pl031.rs index 15e20f81446..754899a23a4 100644 --- a/src/vmm/src/devices/legacy/rtc_pl031.rs +++ b/src/vmm/src/devices/legacy/rtc_pl031.rs @@ -6,7 +6,7 @@ use std::convert::TryInto; use serde::Serialize; use vm_superio::rtc_pl031::RtcEvents; -use crate::logger::{warn, IncMetric, SharedIncMetric}; +use crate::logger::{IncMetric, SharedIncMetric, warn}; /// Metrics specific to the RTC device. #[derive(Debug, Serialize, Default)] diff --git a/src/vmm/src/devices/virtio/balloon/device.rs b/src/vmm/src/devices/virtio/balloon/device.rs index 9ad34d280b5..9205808a7fd 100644 --- a/src/vmm/src/devices/virtio/balloon/device.rs +++ b/src/vmm/src/devices/virtio/balloon/device.rs @@ -16,7 +16,7 @@ use super::metrics::METRICS; use super::util::{compact_page_frame_numbers, remove_range}; use super::{ BALLOON_DEV_ID, BALLOON_NUM_QUEUES, BALLOON_QUEUE_SIZES, DEFLATE_INDEX, INFLATE_INDEX, - MAX_PAGES_IN_DESC, MAX_PAGE_COMPACT_BUFFER, MIB_TO_4K_PAGES, STATS_INDEX, + MAX_PAGE_COMPACT_BUFFER, MAX_PAGES_IN_DESC, MIB_TO_4K_PAGES, STATS_INDEX, VIRTIO_BALLOON_F_DEFLATE_ON_OOM, VIRTIO_BALLOON_F_STATS_VQ, VIRTIO_BALLOON_PFN_SHIFT, VIRTIO_BALLOON_S_AVAIL, VIRTIO_BALLOON_S_CACHES, VIRTIO_BALLOON_S_HTLB_PGALLOC, VIRTIO_BALLOON_S_HTLB_PGFAIL, VIRTIO_BALLOON_S_MAJFLT, VIRTIO_BALLOON_S_MEMFREE, @@ -636,7 +636,7 @@ pub(crate) mod tests { check_request_completion, invoke_handler_for_queue_event, set_request, }; use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::test_utils::single_region_mem; use crate::vstate::memory::GuestAddress; diff --git a/src/vmm/src/devices/virtio/balloon/event_handler.rs b/src/vmm/src/devices/virtio/balloon/event_handler.rs index 3019d6877de..56ff5c35047 100644 --- a/src/vmm/src/devices/virtio/balloon/event_handler.rs +++ b/src/vmm/src/devices/virtio/balloon/event_handler.rs @@ -4,7 +4,7 @@ use event_manager::{EventOps, Events, MutEventSubscriber}; use vmm_sys_util::epoll::EventSet; -use super::{report_balloon_event_fail, DEFLATE_INDEX, INFLATE_INDEX, STATS_INDEX}; +use super::{DEFLATE_INDEX, INFLATE_INDEX, STATS_INDEX, report_balloon_event_fail}; use crate::devices::virtio::balloon::device::Balloon; use crate::devices::virtio::device::VirtioDevice; use crate::logger::{error, warn}; @@ -136,7 +136,7 @@ pub mod tests { use super::*; use crate::devices::virtio::balloon::test_utils::set_request; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::vstate::memory::GuestAddress; #[test] diff --git a/src/vmm/src/devices/virtio/balloon/persist.rs b/src/vmm/src/devices/virtio/balloon/persist.rs index c1fb6865b5f..004fa27f8ca 100644 --- a/src/vmm/src/devices/virtio/balloon/persist.rs +++ b/src/vmm/src/devices/virtio/balloon/persist.rs @@ -3,19 +3,19 @@ //! Defines the structures needed for saving/restoring balloon devices. -use std::sync::atomic::AtomicU32; use std::sync::Arc; +use std::sync::atomic::AtomicU32; use std::time::Duration; use serde::{Deserialize, Serialize}; use timerfd::{SetTimeFlags, TimerState}; use super::*; +use crate::devices::virtio::TYPE_BALLOON; use crate::devices::virtio::balloon::device::{BalloonStats, ConfigSpace}; use crate::devices::virtio::device::DeviceState; use crate::devices::virtio::persist::VirtioDeviceState; use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; -use crate::devices::virtio::TYPE_BALLOON; use crate::snapshot::Persist; use crate::vstate::memory::GuestMemoryMmap; @@ -181,9 +181,9 @@ mod tests { use std::sync::atomic::Ordering; use super::*; + use crate::devices::virtio::TYPE_BALLOON; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::test_utils::default_mem; - use crate::devices::virtio::TYPE_BALLOON; use crate::snapshot::Snapshot; #[test] diff --git a/src/vmm/src/devices/virtio/balloon/test_utils.rs b/src/vmm/src/devices/virtio/balloon/test_utils.rs index 8968aa70915..af0d7f5845e 100644 --- a/src/vmm/src/devices/virtio/balloon/test_utils.rs +++ b/src/vmm/src/devices/virtio/balloon/test_utils.rs @@ -5,7 +5,7 @@ use crate::devices::virtio::test_utils::VirtQueue; #[cfg(test)] -use crate::devices::virtio::{balloon::Balloon, balloon::BALLOON_NUM_QUEUES}; +use crate::devices::virtio::{balloon::BALLOON_NUM_QUEUES, balloon::Balloon}; #[cfg(test)] pub fn invoke_handler_for_queue_event(b: &mut Balloon, queue_index: usize) { diff --git a/src/vmm/src/devices/virtio/balloon/util.rs b/src/vmm/src/devices/virtio/balloon/util.rs index a9960540a60..35ef69f972f 100644 --- a/src/vmm/src/devices/virtio/balloon/util.rs +++ b/src/vmm/src/devices/virtio/balloon/util.rs @@ -3,7 +3,7 @@ use std::io; -use super::{RemoveRegionError, MAX_PAGE_COMPACT_BUFFER}; +use super::{MAX_PAGE_COMPACT_BUFFER, RemoveRegionError}; use crate::logger::error; use crate::utils::u64_to_usize; use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; @@ -125,9 +125,7 @@ mod tests { /// This asserts that $lhs matches $rhs. macro_rules! assert_match { - ($lhs:expr, $rhs:pat) => {{ - assert!(matches!($lhs, $rhs)) - }}; + ($lhs:expr, $rhs:pat) => {{ assert!(matches!($lhs, $rhs)) }}; } #[test] diff --git a/src/vmm/src/devices/virtio/block/device.rs b/src/vmm/src/devices/virtio/block/device.rs index 7399fe39a0b..bf3043bcdd4 100644 --- a/src/vmm/src/devices/virtio/block/device.rs +++ b/src/vmm/src/devices/virtio/block/device.rs @@ -4,10 +4,10 @@ use event_manager::{EventOps, Events, MutEventSubscriber}; use vmm_sys_util::eventfd::EventFd; +use super::BlockError; use super::persist::{BlockConstructorArgs, BlockState}; use super::vhost_user::device::{VhostUserBlock, VhostUserBlockConfig}; use super::virtio::device::{VirtioBlock, VirtioBlockConfig}; -use super::BlockError; use crate::devices::virtio::device::{IrqTrigger, VirtioDevice}; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::{ActivateError, TYPE_BLOCK}; diff --git a/src/vmm/src/devices/virtio/block/vhost_user/device.rs b/src/vmm/src/devices/virtio/block/vhost_user/device.rs index b8c7a6677df..34948035c6b 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/device.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/device.rs @@ -7,12 +7,12 @@ use std::sync::Arc; use log::error; -use utils::time::{get_time_us, ClockType}; -use vhost::vhost_user::message::*; +use utils::time::{ClockType, get_time_us}; use vhost::vhost_user::Frontend; +use vhost::vhost_user::message::*; use vmm_sys_util::eventfd::EventFd; -use super::{VhostUserBlockError, NUM_QUEUES, QUEUE_SIZE}; +use super::{NUM_QUEUES, QUEUE_SIZE, VhostUserBlockError}; use crate::devices::virtio::block::CacheType; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::generated::virtio_blk::{ @@ -25,7 +25,7 @@ use crate::devices::virtio::vhost_user_metrics::{ VhostUserDeviceMetrics, VhostUserMetricsPerDevice, }; use crate::devices::virtio::{ActivateError, TYPE_BLOCK}; -use crate::logger::{log_dev_preview_warning, IncMetric, StoreMetric}; +use crate::logger::{IncMetric, StoreMetric, log_dev_preview_warning}; use crate::utils::u64_to_usize; use crate::vmm_config::drive::BlockDeviceConfig; use crate::vstate::memory::GuestMemoryMmap; diff --git a/src/vmm/src/devices/virtio/block/vhost_user/persist.rs b/src/vmm/src/devices/virtio/block/vhost_user/persist.rs index abaa20e012c..d507fa9577b 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/persist.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/persist.rs @@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize}; -use super::device::VhostUserBlock; use super::VhostUserBlockError; -use crate::devices::virtio::block::persist::BlockConstructorArgs; +use super::device::VhostUserBlock; use crate::devices::virtio::block::CacheType; +use crate::devices::virtio::block::persist::BlockConstructorArgs; use crate::devices::virtio::persist::VirtioDeviceState; use crate::snapshot::Persist; diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index b8d8d588a56..bb374bce5b9 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -20,9 +20,9 @@ use vmm_sys_util::eventfd::EventFd; use super::io::async_io; use super::request::*; -use super::{io as block_io, VirtioBlockError, BLOCK_QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE}; -use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice}; +use super::{BLOCK_QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE, VirtioBlockError, io as block_io}; use crate::devices::virtio::block::CacheType; +use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice}; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::generated::virtio_blk::{ VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_BLK_ID_BYTES, VIRTIO_F_VERSION_1, @@ -30,11 +30,11 @@ use crate::devices::virtio::generated::virtio_blk::{ use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::{ActivateError, TYPE_BLOCK}; -use crate::logger::{error, warn, IncMetric}; +use crate::logger::{IncMetric, error, warn}; use crate::rate_limiter::{BucketUpdate, RateLimiter}; use crate::utils::u64_to_usize; -use crate::vmm_config::drive::BlockDeviceConfig; use crate::vmm_config::RateLimiterConfig; +use crate::vmm_config::drive::BlockDeviceConfig; use crate::vstate::memory::GuestMemoryMmap; /// The engine file type, either Sync or Async (through io_uring). @@ -676,14 +676,14 @@ mod tests { use super::*; use crate::check_metric_after_block; + use crate::devices::virtio::block::virtio::IO_URING_NUM_ENTRIES; use crate::devices::virtio::block::virtio::test_utils::{ default_block, read_blk_req_descriptors, set_queue, set_rate_limiter, simulate_async_completion_event, simulate_queue_and_async_completion_events, simulate_queue_event, }; - use crate::devices::virtio::block::virtio::IO_URING_NUM_ENTRIES; use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::rate_limiter::TokenType; use crate::vstate::memory::{Address, Bytes, GuestAddress}; 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 8400766e06b..db69e23d7f0 100644 --- a/src/vmm/src/devices/virtio/block/virtio/event_handler.rs +++ b/src/vmm/src/devices/virtio/block/virtio/event_handler.rs @@ -124,7 +124,7 @@ mod tests { }; use crate::devices::virtio::block::virtio::{VIRTIO_BLK_S_OK, VIRTIO_BLK_T_OUT}; use crate::devices::virtio::queue::VIRTQ_DESC_F_NEXT; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::vstate::memory::{Bytes, GuestAddress}; #[test] diff --git a/src/vmm/src/devices/virtio/block/virtio/io/async_io.rs b/src/vmm/src/devices/virtio/block/virtio/io/async_io.rs index 515ff9ca32c..3073b55886a 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/async_io.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/async_io.rs @@ -9,8 +9,8 @@ use std::os::unix::io::AsRawFd; use vm_memory::GuestMemoryError; use vmm_sys_util::eventfd::EventFd; -use crate::devices::virtio::block::virtio::io::UserDataError; use crate::devices::virtio::block::virtio::IO_URING_NUM_ENTRIES; +use crate::devices::virtio::block::virtio::io::UserDataError; use crate::io_uring::operation::{Cqe, OpCode, Operation}; use crate::io_uring::restriction::Restriction; use crate::io_uring::{self, IoUring, IoUringError}; diff --git a/src/vmm/src/devices/virtio/block/virtio/persist.rs b/src/vmm/src/devices/virtio/block/virtio/persist.rs index ceceadb3ad9..8c6f2c2453d 100644 --- a/src/vmm/src/devices/virtio/block/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/block/virtio/persist.rs @@ -3,8 +3,8 @@ //! Defines the structures needed for saving/restoring block devices. -use std::sync::atomic::AtomicU32; use std::sync::Arc; +use std::sync::atomic::AtomicU32; use device::ConfigSpace; use serde::{Deserialize, Serialize}; @@ -12,15 +12,15 @@ use vmm_sys_util::eventfd::EventFd; use super::device::DiskProperties; use super::*; +use crate::devices::virtio::TYPE_BLOCK; use crate::devices::virtio::block::persist::BlockConstructorArgs; use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::block::virtio::metrics::BlockMetricsPerDevice; use crate::devices::virtio::device::{DeviceState, IrqTrigger}; use crate::devices::virtio::generated::virtio_blk::VIRTIO_BLK_F_RO; use crate::devices::virtio::persist::VirtioDeviceState; -use crate::devices::virtio::TYPE_BLOCK; -use crate::rate_limiter::persist::RateLimiterState; use crate::rate_limiter::RateLimiter; +use crate::rate_limiter::persist::RateLimiterState; use crate::snapshot::Persist; /// Holds info about block's file engine type. Gets saved in snapshot. diff --git a/src/vmm/src/devices/virtio/block/virtio/request.rs b/src/vmm/src/devices/virtio/block/virtio/request.rs index 8695ad4229e..f8b3172c5c4 100644 --- a/src/vmm/src/devices/virtio/block/virtio/request.rs +++ b/src/vmm/src/devices/virtio/block/virtio/request.rs @@ -9,7 +9,7 @@ use std::convert::From; use vm_memory::GuestMemoryError; -use super::{io as block_io, VirtioBlockError, SECTOR_SHIFT, SECTOR_SIZE}; +use super::{SECTOR_SHIFT, SECTOR_SIZE, VirtioBlockError, io as block_io}; use crate::devices::virtio::block::virtio::device::DiskProperties; use crate::devices::virtio::block::virtio::metrics::BlockDeviceMetrics; pub use crate::devices::virtio::generated::virtio_blk::{ @@ -17,7 +17,7 @@ pub use crate::devices::virtio::generated::virtio_blk::{ VIRTIO_BLK_T_FLUSH, VIRTIO_BLK_T_GET_ID, VIRTIO_BLK_T_IN, VIRTIO_BLK_T_OUT, }; use crate::devices::virtio::queue::DescriptorChain; -use crate::logger::{error, IncMetric}; +use crate::logger::{IncMetric, error}; use crate::rate_limiter::{RateLimiter, TokenType}; use crate::vstate::memory::{ByteValued, Bytes, GuestAddress, GuestMemoryMmap}; @@ -421,7 +421,7 @@ mod tests { use super::*; use crate::devices::virtio::queue::{Queue, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::vstate::memory::{Address, GuestAddress, GuestMemory}; const NUM_DISK_SECTORS: u64 = 1024; @@ -736,8 +736,8 @@ mod tests { } #[allow(clippy::let_with_type_underscore)] - fn random_request_parse( - ) -> impl Strategy, GuestMemoryMmap, Queue)> { + fn random_request_parse() + -> impl Strategy, GuestMemoryMmap, Queue)> { // In this strategy we are going to generate random Requests/Errors and map them // to an input descriptor chain. // diff --git a/src/vmm/src/devices/virtio/block/virtio/test_utils.rs b/src/vmm/src/devices/virtio/block/virtio/test_utils.rs index 106da8177cd..02dd34fbce9 100644 --- a/src/vmm/src/devices/virtio/block/virtio/test_utils.rs +++ b/src/vmm/src/devices/virtio/block/virtio/test_utils.rs @@ -10,8 +10,8 @@ use std::time::Duration; use vmm_sys_util::tempfile::TempFile; -use super::device::VirtioBlockConfig; use super::RequestHeader; +use super::device::VirtioBlockConfig; use crate::devices::virtio::block::virtio::device::FileEngineType; #[cfg(test)] use crate::devices::virtio::block::virtio::io::FileEngine; diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs index d6d5d28386b..62131e775f5 100644 --- a/src/vmm/src/devices/virtio/device.rs +++ b/src/vmm/src/devices/virtio/device.rs @@ -6,14 +6,14 @@ // found in the THIRD-PARTY file. use std::fmt; -use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU32, Ordering}; use vmm_sys_util::eventfd::EventFd; +use super::ActivateError; use super::mmio::{VIRTIO_MMIO_INT_CONFIG, VIRTIO_MMIO_INT_VRING}; use super::queue::{Queue, QueueError}; -use super::ActivateError; use crate::devices::virtio::AsAny; use crate::logger::{error, warn}; use crate::vstate::memory::GuestMemoryMmap; diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index b4028a217b1..3865cc7ecf2 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -197,7 +197,7 @@ impl IoVecBuffer { Err(VolatileMemoryError::IOError(err)) if err.kind() == ErrorKind::Interrupted => { - continue + continue; } Ok(bytes_read) => break bytes_read, Err(volatile_memory_error) => return Err(volatile_memory_error), @@ -462,7 +462,7 @@ impl IoVecBufferMut { Err(VolatileMemoryError::IOError(err)) if err.kind() == ErrorKind::Interrupted => { - continue + continue; } Ok(bytes_read) => break bytes_read, Err(volatile_memory_error) => return Err(volatile_memory_error), @@ -493,7 +493,7 @@ mod tests { use crate::devices::virtio::iov_deque::IovDeque; use crate::devices::virtio::queue::{ - Queue, FIRECRACKER_MAX_QUEUE_SIZE, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE, + FIRECRACKER_MAX_QUEUE_SIZE, Queue, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE, }; use crate::devices::virtio::test_utils::VirtQueue; use crate::test_utils::multi_region_mem; @@ -818,8 +818,8 @@ mod verification { use std::mem::ManuallyDrop; use libc::{c_void, iovec}; - use vm_memory::bitmap::BitmapSlice; use vm_memory::VolatileSlice; + use vm_memory::bitmap::BitmapSlice; use super::IoVecBuffer; use crate::arch::GUEST_PAGE_SIZE; diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs index 63d7a80d84d..12ee54bfb0a 100644 --- a/src/vmm/src/devices/virtio/mmio.rs +++ b/src/vmm/src/devices/virtio/mmio.rs @@ -368,9 +368,9 @@ pub(crate) mod tests { use vmm_sys_util::eventfd::EventFd; use super::*; + use crate::devices::virtio::ActivateError; use crate::devices::virtio::device::IrqTrigger; use crate::devices::virtio::device_status::DEVICE_NEEDS_RESET; - use crate::devices::virtio::ActivateError; use crate::test_utils::single_region_mem; use crate::utils::byte_order::{read_le_u32, write_le_u32}; use crate::utils::u64_to_usize; diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 885abb812f0..38f6f7ee147 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -10,7 +10,7 @@ use std::mem::{self}; use std::net::Ipv4Addr; use std::sync::{Arc, Mutex}; -use libc::{iovec, EAGAIN}; +use libc::{EAGAIN, iovec}; use log::error; use vmm_sys_util::eventfd::EventFd; @@ -18,9 +18,9 @@ use super::NET_QUEUE_MAX_SIZE; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::generated::virtio_blk::VIRTIO_F_VERSION_1; use crate::devices::virtio::generated::virtio_net::{ - virtio_net_hdr_v1, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_TSO4, - VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_HOST_TSO4, - VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, + VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_UFO, + VIRTIO_NET_F_MAC, VIRTIO_NET_F_MRG_RXBUF, virtio_net_hdr_v1, }; use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::iovec::{ @@ -29,11 +29,11 @@ use crate::devices::virtio::iovec::{ use crate::devices::virtio::net::metrics::{NetDeviceMetrics, NetMetricsPerDevice}; use crate::devices::virtio::net::tap::Tap; use crate::devices::virtio::net::{ - generated, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX, + MAX_BUFFER_SIZE, NET_QUEUE_SIZES, NetError, NetQueue, RX_INDEX, TX_INDEX, generated, }; use crate::devices::virtio::queue::{DescriptorChain, Queue}; use crate::devices::virtio::{ActivateError, TYPE_NET}; -use crate::devices::{report_net_event_fail, DeviceError}; +use crate::devices::{DeviceError, report_net_event_fail}; use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN; use crate::dumbo::pdu::ethernet::{EthernetFrame, PAYLOAD_OFFSET}; use crate::logger::{IncMetric, METRICS}; @@ -1042,24 +1042,24 @@ pub mod tests { use crate::check_metric_after_block; use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::iovec::IoVecBuffer; + use crate::devices::virtio::net::NET_QUEUE_SIZES; use crate::devices::virtio::net::device::{ frame_bytes_from_buf, frame_bytes_from_buf_mut, frame_hdr_len, init_vnet_hdr, vnet_hdr_len, }; use crate::devices::virtio::net::test_utils::test::TestHelper; use crate::devices::virtio::net::test_utils::{ - default_net, if_index, inject_tap_tx_frame, set_mac, NetEvent, NetQueue, - TapTrafficSimulator, + NetEvent, NetQueue, TapTrafficSimulator, default_net, if_index, inject_tap_tx_frame, + set_mac, }; - use crate::devices::virtio::net::NET_QUEUE_SIZES; use crate::devices::virtio::queue::VIRTQ_DESC_F_WRITE; use crate::devices::virtio::test_utils::VirtQueue; - use crate::dumbo::pdu::arp::{EthIPv4ArpFrame, ETH_IPV4_FRAME_LEN}; - use crate::dumbo::pdu::ethernet::ETHERTYPE_ARP; use crate::dumbo::EthernetFrame; + use crate::dumbo::pdu::arp::{ETH_IPV4_FRAME_LEN, EthIPv4ArpFrame}; + use crate::dumbo::pdu::ethernet::ETHERTYPE_ARP; use crate::logger::IncMetric; use crate::rate_limiter::{BucketUpdate, RateLimiter, TokenBucket, TokenType}; use crate::test_utils::single_region_mem; - use crate::utils::net::mac::{MacAddr, MAC_ADDR_LEN}; + use crate::utils::net::mac::{MAC_ADDR_LEN, MacAddr}; use crate::vstate::memory::{Address, GuestMemory}; impl Net { @@ -1153,8 +1153,10 @@ pub mod tests { | (1 << VIRTIO_NET_F_GUEST_UFO) | (1 << VIRTIO_NET_F_GUEST_TSO4) | (1 << VIRTIO_NET_F_GUEST_TSO6); - let expected_tap_features = - generated::TUN_F_CSUM | generated::TUN_F_UFO | generated::TUN_F_TSO4 | generated::TUN_F_TSO6; + let expected_tap_features = generated::TUN_F_CSUM + | generated::TUN_F_UFO + | generated::TUN_F_TSO4 + | generated::TUN_F_TSO6; let supported_flags = Net::build_tap_offload_features(supported_features); assert_eq!(supported_flags, expected_tap_features); @@ -1920,16 +1922,18 @@ pub mod tests { check_metric_after_block!( &METRICS.mmds.rx_accepted, 1, - assert!(Net::write_to_mmds_or_tap( - net.mmds_ns.as_mut(), - &mut net.tx_rate_limiter, - &mut headers, - &buffer, - &mut net.tap, - Some(src_mac), - &net.metrics, + assert!( + Net::write_to_mmds_or_tap( + net.mmds_ns.as_mut(), + &mut net.tx_rate_limiter, + &mut headers, + &buffer, + &mut net.tap, + Some(src_mac), + &net.metrics, + ) + .unwrap() ) - .unwrap()) ); // Validate that MMDS has a response and we can retrieve it. diff --git a/src/vmm/src/devices/virtio/net/event_handler.rs b/src/vmm/src/devices/virtio/net/event_handler.rs index 1d8805e93fe..9d8c09a45f2 100644 --- a/src/vmm/src/devices/virtio/net/event_handler.rs +++ b/src/vmm/src/devices/virtio/net/event_handler.rs @@ -7,7 +7,7 @@ use vmm_sys_util::epoll::EventSet; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::net::device::Net; use crate::devices::virtio::net::{RX_INDEX, TX_INDEX}; -use crate::logger::{error, warn, IncMetric}; +use crate::logger::{IncMetric, error, warn}; impl Net { const PROCESS_ACTIVATE: u32 = 0; @@ -132,8 +132,8 @@ impl MutEventSubscriber for Net { #[cfg(test)] pub mod tests { - use crate::devices::virtio::net::test_utils::test::TestHelper; use crate::devices::virtio::net::test_utils::NetQueue; + use crate::devices::virtio::net::test_utils::test::TestHelper; use crate::devices::virtio::net::{MAX_BUFFER_SIZE, TX_INDEX}; use crate::test_utils::single_region_mem; diff --git a/src/vmm/src/devices/virtio/net/persist.rs b/src/vmm/src/devices/virtio/net/persist.rs index fb62dcb0abe..66493f0f334 100644 --- a/src/vmm/src/devices/virtio/net/persist.rs +++ b/src/vmm/src/devices/virtio/net/persist.rs @@ -10,15 +10,15 @@ use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; use super::device::{Net, RxBuffers}; -use super::{TapError, NET_NUM_QUEUES, NET_QUEUE_MAX_SIZE, RX_INDEX}; +use super::{NET_NUM_QUEUES, NET_QUEUE_MAX_SIZE, RX_INDEX, TapError}; +use crate::devices::virtio::TYPE_NET; use crate::devices::virtio::device::DeviceState; use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState}; -use crate::devices::virtio::TYPE_NET; use crate::mmds::data_store::Mmds; use crate::mmds::ns::MmdsNetworkStack; use crate::mmds::persist::MmdsNetworkStackState; -use crate::rate_limiter::persist::RateLimiterState; use crate::rate_limiter::RateLimiter; +use crate::rate_limiter::persist::RateLimiterState; use crate::snapshot::Persist; use crate::utils::net::mac::MacAddr; use crate::vstate::memory::GuestMemoryMmap; diff --git a/src/vmm/src/devices/virtio/net/tap.rs b/src/vmm/src/devices/virtio/net/tap.rs index 7b3b7b01142..c516705af31 100644 --- a/src/vmm/src/devices/virtio/net/tap.rs +++ b/src/vmm/src/devices/virtio/net/tap.rs @@ -136,7 +136,10 @@ impl Tap { let terminated_if_name = build_terminated_if_name(if_name)?; let ifreq = IfReqBuilder::new() .if_name(&terminated_if_name) - .flags(i16::try_from(generated::IFF_TAP | generated::IFF_NO_PI | generated::IFF_VNET_HDR).unwrap()) + .flags( + i16::try_from(generated::IFF_TAP | generated::IFF_NO_PI | generated::IFF_VNET_HDR) + .unwrap(), + ) .execute(&tuntap, TUNSETIFF()) .map_err(|io_error| TapError::IfreqExecuteError(io_error, if_name.to_owned()))?; @@ -220,7 +223,7 @@ pub mod tests { use super::*; use crate::devices::virtio::net::generated; - use crate::devices::virtio::net::test_utils::{enable, if_index, TapTrafficSimulator}; + use crate::devices::virtio::net::test_utils::{TapTrafficSimulator, enable, if_index}; // Redefine `IoVecBufferMut` with specific length. Otherwise // Rust will not know what to do. diff --git a/src/vmm/src/devices/virtio/net/test_utils.rs b/src/vmm/src/devices/virtio/net/test_utils.rs index 167f4f909b8..5762123be68 100644 --- a/src/vmm/src/devices/virtio/net/test_utils.rs +++ b/src/vmm/src/devices/virtio/net/test_utils.rs @@ -12,13 +12,13 @@ use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; +use crate::devices::DeviceError; +use crate::devices::virtio::net::Net; #[cfg(test)] use crate::devices::virtio::net::device::vnet_hdr_len; use crate::devices::virtio::net::tap::{IfReqBuilder, Tap}; -use crate::devices::virtio::net::Net; use crate::devices::virtio::queue::{Queue, QueueError}; use crate::devices::virtio::test_utils::VirtQueue; -use crate::devices::DeviceError; use crate::mmds::data_store::Mmds; use crate::mmds::ns::MmdsNetworkStack; use crate::rate_limiter::RateLimiter; @@ -211,7 +211,10 @@ pub fn if_index(tap: &Tap) -> i32 { let sock = create_socket(); let ifreq = IfReqBuilder::new() .if_name(&tap.if_name) - .execute(&sock, c_ulong::from(super::generated::sockios::SIOCGIFINDEX)) + .execute( + &sock, + c_ulong::from(super::generated::sockios::SIOCGIFINDEX), + ) .unwrap(); // SAFETY: Using this union variant is safe since `SIOCGIFINDEX` returns an integer. @@ -240,7 +243,10 @@ pub fn enable(tap: &Tap) { .try_into() .unwrap(), ) - .execute(&sock, c_ulong::from(super::generated::sockios::SIOCSIFFLAGS)) + .execute( + &sock, + c_ulong::from(super::generated::sockios::SIOCSIFFLAGS), + ) .unwrap(); } @@ -309,9 +315,9 @@ pub mod test { use crate::devices::virtio::net::device::vnet_hdr_len; use crate::devices::virtio::net::generated::ETH_HLEN; use crate::devices::virtio::net::test_utils::{ - assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue, + NetEvent, NetQueue, assign_queues, default_net, inject_tap_tx_frame, }; - use crate::devices::virtio::net::{Net, MAX_BUFFER_SIZE, RX_INDEX, TX_INDEX}; + use crate::devices::virtio::net::{MAX_BUFFER_SIZE, Net, RX_INDEX, TX_INDEX}; use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE}; use crate::devices::virtio::test_utils::{VirtQueue, VirtqDesc}; use crate::logger::IncMetric; diff --git a/src/vmm/src/devices/virtio/persist.rs b/src/vmm/src/devices/virtio/persist.rs index cd7d1245dd9..7551921f4b0 100644 --- a/src/vmm/src/devices/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/persist.rs @@ -258,12 +258,12 @@ mod tests { use vmm_sys_util::tempfile::TempFile; use super::*; + use crate::devices::virtio::block::virtio::VirtioBlock; use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::block::virtio::test_utils::default_block_with_path; - use crate::devices::virtio::block::virtio::VirtioBlock; use crate::devices::virtio::mmio::tests::DummyDevice; - use crate::devices::virtio::net::test_utils::default_net; use crate::devices::virtio::net::Net; + use crate::devices::virtio::net::test_utils::default_net; use crate::devices::virtio::test_utils::default_mem; use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend}; use crate::snapshot::Snapshot; diff --git a/src/vmm/src/devices/virtio/queue.rs b/src/vmm/src/devices/virtio/queue.rs index d84c4988d62..efe42bfc3dc 100644 --- a/src/vmm/src/devices/virtio/queue.rs +++ b/src/vmm/src/devices/virtio/queue.rs @@ -7,7 +7,7 @@ use std::cmp::min; use std::num::Wrapping; -use std::sync::atomic::{fence, Ordering}; +use std::sync::atomic::{Ordering, fence}; use crate::logger::error; use crate::vstate::memory::{Address, Bitmap, ByteValued, GuestAddress, GuestMemory}; @@ -116,11 +116,7 @@ impl DescriptorChain { next: desc.next, }; - if chain.is_valid() { - Some(chain) - } else { - None - } + if chain.is_valid() { Some(chain) } else { None } } fn is_valid(&self) -> bool { @@ -955,8 +951,8 @@ mod verification { #[kani::proof] #[kani::unwind(0)] // There are no loops anywhere, but kani really enjoys getting stuck in std::ptr::drop_in_place. - // This is a compiler intrinsic that has a "dummy" implementation in stdlib that just - // recursively calls itself. Kani will generally unwind this recursion infinitely + // This is a compiler intrinsic that has a "dummy" implementation in stdlib that just + // recursively calls itself. Kani will generally unwind this recursion infinitely fn verify_spec_2_6_7_2() { // Section 2.6.7.2 deals with device-to-driver notification suppression. // It describes a mechanism by which the driver can tell the device that it does not @@ -1091,11 +1087,7 @@ mod verification { // Section 2.6: Alignment of descriptor table, available ring and used ring; size of // queue fn alignment_of(val: u64) -> u64 { - if val == 0 { - u64::MAX - } else { - val & (!val + 1) - } + if val == 0 { u64::MAX } else { val & (!val + 1) } } assert!(alignment_of(queue.desc_table_address.0) >= 16); @@ -1265,7 +1257,7 @@ mod tests { pub use super::*; use crate::devices::virtio::queue::QueueError::DescIndexOutOfBounds; - use crate::devices::virtio::test_utils::{default_mem, VirtQueue}; + use crate::devices::virtio::test_utils::{VirtQueue, default_mem}; use crate::test_utils::{multi_region_mem, single_region_mem}; use crate::vstate::memory::GuestAddress; diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs index a6e9055e0a0..9c9021b66d9 100644 --- a/src/vmm/src/devices/virtio/rng/device.rs +++ b/src/vmm/src/devices/virtio/rng/device.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use std::io; -use std::sync::atomic::AtomicU32; use std::sync::Arc; +use std::sync::atomic::AtomicU32; use aws_lc_rs::rand; use vm_memory::GuestMemoryError; @@ -11,14 +11,14 @@ use vmm_sys_util::eventfd::EventFd; use super::metrics::METRICS; use super::{RNG_NUM_QUEUES, RNG_QUEUE}; +use crate::devices::DeviceError; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::generated::virtio_rng::VIRTIO_F_VERSION_1; use crate::devices::virtio::iov_deque::IovDequeError; use crate::devices::virtio::iovec::IoVecBufferMut; -use crate::devices::virtio::queue::{Queue, FIRECRACKER_MAX_QUEUE_SIZE}; +use crate::devices::virtio::queue::{FIRECRACKER_MAX_QUEUE_SIZE, Queue}; use crate::devices::virtio::{ActivateError, TYPE_RNG}; -use crate::devices::DeviceError; -use crate::logger::{debug, error, IncMetric}; +use crate::logger::{IncMetric, debug, error}; use crate::rate_limiter::{RateLimiter, TokenType}; use crate::vstate::memory::GuestMemoryMmap; @@ -314,7 +314,7 @@ mod tests { use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::queue::VIRTQ_DESC_F_WRITE; use crate::devices::virtio::test_utils::test::{ - create_virtio_mem, VirtioTestDevice, VirtioTestHelper, + VirtioTestDevice, VirtioTestHelper, create_virtio_mem, }; impl VirtioTestDevice for Entropy { diff --git a/src/vmm/src/devices/virtio/rng/persist.rs b/src/vmm/src/devices/virtio/rng/persist.rs index 4aa9e449344..2f2519b4962 100644 --- a/src/vmm/src/devices/virtio/rng/persist.rs +++ b/src/vmm/src/devices/virtio/rng/persist.rs @@ -5,12 +5,12 @@ use serde::{Deserialize, Serialize}; +use crate::devices::virtio::TYPE_RNG; use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState}; use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; use crate::devices::virtio::rng::{Entropy, EntropyError, RNG_NUM_QUEUES}; -use crate::devices::virtio::TYPE_RNG; -use crate::rate_limiter::persist::RateLimiterState; use crate::rate_limiter::RateLimiter; +use crate::rate_limiter::persist::RateLimiterState; use crate::snapshot::Persist; use crate::vstate::memory::GuestMemoryMmap; diff --git a/src/vmm/src/devices/virtio/vhost_user.rs b/src/vmm/src/devices/virtio/vhost_user.rs index cca506a57c2..59efcb1a653 100644 --- a/src/vmm/src/devices/virtio/vhost_user.rs +++ b/src/vmm/src/devices/virtio/vhost_user.rs @@ -373,7 +373,7 @@ impl VhostUserHandleImpl { None => { return Err(VhostUserError::VhostUserMemoryRegion( MmapError::NoMemoryRegion, - )) + )); } }; diff --git a/src/vmm/src/devices/virtio/vhost_user_metrics.rs b/src/vmm/src/devices/virtio/vhost_user_metrics.rs index 0a3c8cd3a6a..bb7f03b30a6 100644 --- a/src/vmm/src/devices/virtio/vhost_user_metrics.rs +++ b/src/vmm/src/devices/virtio/vhost_user_metrics.rs @@ -144,7 +144,7 @@ pub struct VhostUserDeviceMetrics { #[cfg(test)] pub mod tests { - use utils::time::{get_time_us, ClockType}; + use utils::time::{ClockType, get_time_us}; use super::*; use crate::logger::{IncMetric, StoreMetric}; diff --git a/src/vmm/src/devices/virtio/vsock/csm/connection.rs b/src/vmm/src/devices/virtio/vsock/csm/connection.rs index ad2340413f6..c9bd5b2c0f7 100644 --- a/src/vmm/src/devices/virtio/vsock/csm/connection.rs +++ b/src/vmm/src/devices/virtio/vsock/csm/connection.rs @@ -83,14 +83,14 @@ use std::os::unix::io::{AsRawFd, RawFd}; use std::time::{Duration, Instant}; use log::{debug, error, info, warn}; -use vm_memory::io::{ReadVolatile, WriteVolatile}; use vm_memory::GuestMemoryError; +use vm_memory::io::{ReadVolatile, WriteVolatile}; use vmm_sys_util::epoll::EventSet; use super::super::defs::uapi; use super::super::{VsockChannel, VsockEpollListener, VsockError}; use super::txbuf::TxBuf; -use super::{defs, ConnState, PendingRx, PendingRxSet, VsockCsmError}; +use super::{ConnState, PendingRx, PendingRxSet, VsockCsmError, defs}; use crate::devices::virtio::vsock::metrics::METRICS; use crate::devices::virtio::vsock::packet::{VsockPacketHeader, VsockPacketRx, VsockPacketTx}; use crate::logger::IncMetric; diff --git a/src/vmm/src/devices/virtio/vsock/csm/txbuf.rs b/src/vmm/src/devices/virtio/vsock/csm/txbuf.rs index 1742b02394f..d507491e8a0 100644 --- a/src/vmm/src/devices/virtio/vsock/csm/txbuf.rs +++ b/src/vmm/src/devices/virtio/vsock/csm/txbuf.rs @@ -8,7 +8,7 @@ use std::num::Wrapping; use vm_memory::{VolatileMemoryError, VolatileSlice, WriteVolatile}; -use super::{defs, VsockCsmError}; +use super::{VsockCsmError, defs}; use crate::utils::wrap_usize_to_u32; use crate::vstate::memory::{BitmapSlice, Bytes}; diff --git a/src/vmm/src/devices/virtio/vsock/device.rs b/src/vmm/src/devices/virtio/vsock/device.rs index ec0404bcd9a..4626484ab2a 100644 --- a/src/vmm/src/devices/virtio/vsock/device.rs +++ b/src/vmm/src/devices/virtio/vsock/device.rs @@ -27,13 +27,13 @@ use vmm_sys_util::eventfd::EventFd; use super::super::super::DeviceError; use super::defs::uapi; -use super::packet::{VsockPacketRx, VsockPacketTx, VSOCK_PKT_HDR_SIZE}; -use super::{defs, VsockBackend}; +use super::packet::{VSOCK_PKT_HDR_SIZE, VsockPacketRx, VsockPacketTx}; +use super::{VsockBackend, defs}; +use crate::devices::virtio::ActivateError; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::queue::Queue as VirtQueue; -use crate::devices::virtio::vsock::metrics::METRICS; use crate::devices::virtio::vsock::VsockError; -use crate::devices::virtio::ActivateError; +use crate::devices::virtio::vsock::metrics::METRICS; use crate::logger::IncMetric; use crate::utils::byte_order; use crate::vstate::memory::{Bytes, GuestMemoryMmap}; diff --git a/src/vmm/src/devices/virtio/vsock/event_handler.rs b/src/vmm/src/devices/virtio/vsock/event_handler.rs index 59cf3fe0103..a16cff7dbfc 100755 --- a/src/vmm/src/devices/virtio/vsock/event_handler.rs +++ b/src/vmm/src/devices/virtio/vsock/event_handler.rs @@ -30,8 +30,8 @@ use event_manager::{EventOps, Events, MutEventSubscriber}; use log::{error, warn}; use vmm_sys_util::epoll::EventSet; -use super::device::{Vsock, EVQ_INDEX, RXQ_INDEX, TXQ_INDEX}; use super::VsockBackend; +use super::device::{EVQ_INDEX, RXQ_INDEX, TXQ_INDEX, Vsock}; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::vsock::metrics::METRICS; use crate::logger::IncMetric; diff --git a/src/vmm/src/devices/virtio/vsock/mod.rs b/src/vmm/src/devices/virtio/vsock/mod.rs index 8ffaaa8db0d..fe338e95763 100644 --- a/src/vmm/src/devices/virtio/vsock/mod.rs +++ b/src/vmm/src/devices/virtio/vsock/mod.rs @@ -25,8 +25,8 @@ use std::os::unix::io::AsRawFd; use vm_memory::GuestMemoryError; use vmm_sys_util::epoll::EventSet; -pub use self::defs::uapi::VIRTIO_ID_VSOCK as TYPE_VSOCK; pub use self::defs::VSOCK_DEV_ID; +pub use self::defs::uapi::VIRTIO_ID_VSOCK as TYPE_VSOCK; pub use self::device::Vsock; use self::packet::{VsockPacketRx, VsockPacketTx}; pub use self::unix::{VsockUnixBackend, VsockUnixBackendError}; diff --git a/src/vmm/src/devices/virtio/vsock/packet.rs b/src/vmm/src/devices/virtio/vsock/packet.rs index 0927dcf7323..78130af4b12 100644 --- a/src/vmm/src/devices/virtio/vsock/packet.rs +++ b/src/vmm/src/devices/virtio/vsock/packet.rs @@ -21,7 +21,7 @@ use std::fmt::Debug; use vm_memory::volatile_memory::Error; use vm_memory::{GuestMemoryError, ReadVolatile, WriteVolatile}; -use super::{defs, VsockError}; +use super::{VsockError, defs}; use crate::devices::virtio::iovec::{IoVecBuffer, IoVecBufferMut}; use crate::devices::virtio::queue::DescriptorChain; use crate::vstate::memory::{ByteValued, GuestMemoryMmap}; @@ -223,7 +223,7 @@ impl VsockPacketTx { match self.buffer.read_exact_volatile_at(hdr.as_mut_slice(), 0) { Ok(()) => (), Err(Error::PartialBuffer { completed, .. }) => { - return Err(VsockError::DescChainTooShortForHeader(completed)) + return Err(VsockError::DescChainTooShortForHeader(completed)); } Err(err) => return Err(VsockError::GuestMemoryMmap(err.into())), } diff --git a/src/vmm/src/devices/virtio/vsock/persist.rs b/src/vmm/src/devices/virtio/vsock/persist.rs index dce545fd68d..fce6affae69 100644 --- a/src/vmm/src/devices/virtio/vsock/persist.rs +++ b/src/vmm/src/devices/virtio/vsock/persist.rs @@ -4,8 +4,8 @@ //! Defines state and support structures for persisting Vsock devices and backends. use std::fmt::Debug; -use std::sync::atomic::AtomicU32; use std::sync::Arc; +use std::sync::atomic::AtomicU32; use serde::{Deserialize, Serialize}; diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs index 84273f45aba..478d5c7318d 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer.rs @@ -44,7 +44,7 @@ use super::super::defs::uapi; use super::super::{VsockBackend, VsockChannel, VsockEpollListener, VsockError}; use super::muxer_killq::MuxerKillQ; use super::muxer_rxq::MuxerRxQ; -use super::{defs, MuxerConnection, VsockUnixBackendError}; +use super::{MuxerConnection, VsockUnixBackendError, defs}; use crate::devices::virtio::vsock::metrics::METRICS; use crate::devices::virtio::vsock::packet::{VsockPacketRx, VsockPacketTx}; use crate::logger::IncMetric; 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 360dfdf49e9..dc94b38fe36 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs @@ -28,7 +28,7 @@ use std::collections::{HashMap, VecDeque}; use std::time::Instant; use super::muxer::ConnMapKey; -use super::{defs, MuxerConnection}; +use super::{MuxerConnection, defs}; /// A kill queue item, holding the connection key and the scheduled time for termination. #[derive(Debug, Clone, Copy)] diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs index 77f7670af7d..1b888dfa453 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer_rxq.rs @@ -19,7 +19,7 @@ use std::collections::{HashMap, VecDeque}; use super::super::VsockChannel; use super::muxer::{ConnMapKey, MuxerRx}; -use super::{defs, MuxerConnection}; +use super::{MuxerConnection, defs}; /// The muxer RX queue. #[derive(Debug)] diff --git a/src/vmm/src/dumbo/mod.rs b/src/vmm/src/dumbo/mod.rs index e1286c74e93..d39b06d0411 100644 --- a/src/vmm/src/dumbo/mod.rs +++ b/src/vmm/src/dumbo/mod.rs @@ -8,12 +8,12 @@ pub mod tcp; use std::ops::Index; -pub use crate::dumbo::pdu::arp::{EthIPv4ArpFrame, ETH_IPV4_FRAME_LEN}; +pub use crate::dumbo::pdu::arp::{ETH_IPV4_FRAME_LEN, EthIPv4ArpFrame}; pub use crate::dumbo::pdu::ethernet::{ - EthernetFrame, ETHERTYPE_ARP, ETHERTYPE_IPV4, PAYLOAD_OFFSET as ETHERNET_PAYLOAD_OFFSET, + ETHERTYPE_ARP, ETHERTYPE_IPV4, EthernetFrame, PAYLOAD_OFFSET as ETHERNET_PAYLOAD_OFFSET, }; pub use crate::dumbo::pdu::ipv4::{IPv4Packet, PROTOCOL_TCP, PROTOCOL_UDP}; -pub use crate::dumbo::pdu::udp::{UdpDatagram, UDP_HEADER_SIZE}; +pub use crate::dumbo::pdu::udp::{UDP_HEADER_SIZE, UdpDatagram}; use crate::utils::net::mac::MacAddr; /// Represents a generalization of a borrowed `[u8]` slice. diff --git a/src/vmm/src/dumbo/pdu/arp.rs b/src/vmm/src/dumbo/pdu/arp.rs index 54286d281b7..7beef7e4d37 100644 --- a/src/vmm/src/dumbo/pdu/arp.rs +++ b/src/vmm/src/dumbo/pdu/arp.rs @@ -14,7 +14,7 @@ use std::result::Result; use super::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; use super::ethernet::{self, ETHERTYPE_IPV4}; -use crate::utils::net::mac::{MacAddr, MAC_ADDR_LEN}; +use crate::utils::net::mac::{MAC_ADDR_LEN, MacAddr}; /// ARP Request operation pub const OPER_REQUEST: u16 = 0x0001; diff --git a/src/vmm/src/dumbo/pdu/ethernet.rs b/src/vmm/src/dumbo/pdu/ethernet.rs index bec283bbd56..6b7112e36ea 100644 --- a/src/vmm/src/dumbo/pdu/ethernet.rs +++ b/src/vmm/src/dumbo/pdu/ethernet.rs @@ -7,8 +7,8 @@ use std::fmt::Debug; use std::result::Result; -use super::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; use super::Incomplete; +use super::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; use crate::dumbo::MacAddr; const DST_MAC_OFFSET: usize = 0; diff --git a/src/vmm/src/dumbo/pdu/ipv4.rs b/src/vmm/src/dumbo/pdu/ipv4.rs index f3da2b7b298..fab5b88eb49 100644 --- a/src/vmm/src/dumbo/pdu/ipv4.rs +++ b/src/vmm/src/dumbo/pdu/ipv4.rs @@ -13,7 +13,7 @@ use std::net::Ipv4Addr; use std::result::Result; use crate::dumbo::pdu::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; -use crate::dumbo::pdu::{ethernet, Incomplete}; +use crate::dumbo::pdu::{Incomplete, ethernet}; const VERSION_AND_IHL_OFFSET: usize = 0; const DSCP_AND_ECN_OFFSET: usize = 1; diff --git a/src/vmm/src/dumbo/pdu/tcp.rs b/src/vmm/src/dumbo/pdu/tcp.rs index d5eade0c644..2ac01227142 100644 --- a/src/vmm/src/dumbo/pdu/tcp.rs +++ b/src/vmm/src/dumbo/pdu/tcp.rs @@ -15,10 +15,10 @@ use std::result::Result; use bitflags::bitflags; -use super::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; use super::Incomplete; -use crate::dumbo::pdu::ChecksumProto; +use super::bytes::{InnerBytes, NetworkBytes, NetworkBytesMut}; use crate::dumbo::ByteBuffer; +use crate::dumbo::pdu::ChecksumProto; const SOURCE_PORT_OFFSET: usize = 0; const DESTINATION_PORT_OFFSET: usize = 2; diff --git a/src/vmm/src/dumbo/tcp/connection.rs b/src/vmm/src/dumbo/tcp/connection.rs index e17be1063af..016a44477a7 100644 --- a/src/vmm/src/dumbo/tcp/connection.rs +++ b/src/vmm/src/dumbo/tcp/connection.rs @@ -12,13 +12,13 @@ use std::num::{NonZeroU16, NonZeroU64, NonZeroUsize, Wrapping}; use bitflags::bitflags; use vmm_sys_util::rand::xor_pseudo_rng_u32; +use crate::dumbo::ByteBuffer; +use crate::dumbo::pdu::Incomplete; use crate::dumbo::pdu::bytes::NetworkBytes; use crate::dumbo::pdu::tcp::{Flags as TcpFlags, TcpError as TcpSegmentError, TcpSegment}; -use crate::dumbo::pdu::Incomplete; use crate::dumbo::tcp::{ - seq_after, seq_at_or_after, NextSegmentStatus, RstConfig, MAX_WINDOW_SIZE, MSS_DEFAULT, + MAX_WINDOW_SIZE, MSS_DEFAULT, NextSegmentStatus, RstConfig, seq_after, seq_at_or_after, }; -use crate::dumbo::ByteBuffer; bitflags! { // We use a set of flags, instead of a state machine, to represent the connection status. Some diff --git a/src/vmm/src/dumbo/tcp/endpoint.rs b/src/vmm/src/dumbo/tcp/endpoint.rs index 15fb10e10f9..2fbb8466564 100644 --- a/src/vmm/src/dumbo/tcp/endpoint.rs +++ b/src/vmm/src/dumbo/tcp/endpoint.rs @@ -17,11 +17,11 @@ use std::num::{NonZeroU16, NonZeroU64, Wrapping}; use micro_http::{Body, Request, RequestError, Response, StatusCode, Version}; use utils::time::timestamp_cycles; +use crate::dumbo::pdu::Incomplete; use crate::dumbo::pdu::bytes::NetworkBytes; use crate::dumbo::pdu::tcp::TcpSegment; -use crate::dumbo::pdu::Incomplete; use crate::dumbo::tcp::connection::{Connection, PassiveOpenError, RecvStatusFlags}; -use crate::dumbo::tcp::{seq_after, NextSegmentStatus, MAX_WINDOW_SIZE}; +use crate::dumbo::tcp::{MAX_WINDOW_SIZE, NextSegmentStatus, seq_after}; use crate::logger::{IncMetric, METRICS}; // TODO: These are currently expressed in cycles. Normally, they would be the equivalent of a @@ -629,9 +629,11 @@ mod tests { Expect: 100-continue\r\n\ Transfer-Encoding: identity; q=0\r\n\ Content-Length: 26\r\n\r\nthis is not\n\r\na json \nbody"; - assert!(parse_request_bytes(request_bytes, mock_callback) - .body() - .is_none()); + assert!( + parse_request_bytes(request_bytes, mock_callback) + .body() + .is_none() + ); let request_bytes = b"PATCH http://localhost/home HTTP/1.1\r\n\ Expect: 100-continue\r\n\ diff --git a/src/vmm/src/gdb/arch/aarch64.rs b/src/vmm/src/gdb/arch/aarch64.rs index eec7cfa9df8..efd5ad8ae01 100644 --- a/src/vmm/src/gdb/arch/aarch64.rs +++ b/src/vmm/src/gdb/arch/aarch64.rs @@ -5,18 +5,18 @@ use std::mem::offset_of; use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs; use kvm_bindings::{ - kvm_guest_debug, kvm_regs, user_pt_regs, KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP, - KVM_GUESTDBG_USE_HW, KVM_GUESTDBG_USE_SW_BP, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64, + KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP, KVM_GUESTDBG_USE_HW, KVM_GUESTDBG_USE_SW_BP, + KVM_REG_ARM_CORE, KVM_REG_ARM64, KVM_REG_SIZE_U64, kvm_guest_debug, kvm_regs, user_pt_regs, }; use kvm_ioctls::VcpuFd; use vm_memory::{Bytes, GuestAddress}; +use crate::Vmm; use crate::arch::aarch64::regs::{ - arm64_core_reg_id, Aarch64RegisterVec, ID_AA64MMFR0_EL1, TCR_EL1, TTBR1_EL1, + Aarch64RegisterVec, ID_AA64MMFR0_EL1, TCR_EL1, TTBR1_EL1, arm64_core_reg_id, }; use crate::arch::aarch64::vcpu::get_registers; use crate::gdb::target::GdbTargetError; -use crate::Vmm; /// Configures the number of bytes required for a software breakpoint. /// diff --git a/src/vmm/src/gdb/arch/x86.rs b/src/vmm/src/gdb/arch/x86.rs index 16d6789b100..f8df58bedef 100644 --- a/src/vmm/src/gdb/arch/x86.rs +++ b/src/vmm/src/gdb/arch/x86.rs @@ -6,9 +6,9 @@ use kvm_bindings::*; use kvm_ioctls::VcpuFd; use vm_memory::GuestAddress; +use crate::Vmm; use crate::gdb::target::GdbTargetError; use crate::logger::error; -use crate::Vmm; /// Sets the 9th (Global Exact Breakpoint enable) and the 10th (always 1) bits for the DR7 debug /// control register diff --git a/src/vmm/src/gdb/event_loop.rs b/src/vmm/src/gdb/event_loop.rs index ae4de0e64d7..35fe2039f77 100644 --- a/src/vmm/src/gdb/event_loop.rs +++ b/src/vmm/src/gdb/event_loop.rs @@ -14,9 +14,9 @@ use gdbstub::target::Target; use kvm_ioctls::VcpuFd; use vm_memory::GuestAddress; -use super::target::{vcpuid_to_tid, FirecrackerTarget, GdbTargetError}; -use crate::logger::{error, trace}; +use super::target::{FirecrackerTarget, GdbTargetError, vcpuid_to_tid}; use crate::Vmm; +use crate::logger::{error, trace}; /// Starts the GDB event loop which acts as a proxy between the Vcpus and GDB pub fn event_loop( diff --git a/src/vmm/src/gdb/mod.rs b/src/vmm/src/gdb/mod.rs index 9d209541425..23d9965b1aa 100644 --- a/src/vmm/src/gdb/mod.rs +++ b/src/vmm/src/gdb/mod.rs @@ -19,8 +19,8 @@ use kvm_ioctls::VcpuFd; use target::GdbTargetError; use vm_memory::GuestAddress; -use crate::logger::trace; use crate::Vmm; +use crate::logger::trace; /// Kickstarts the GDB debugging process, it takes in the VMM object, a slice of /// the paused Vcpu's, the GDB event queue which is used as a mechanism for the Vcpu's to notify diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index 6f3f2593c15..c9d71e1f14a 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -9,31 +9,31 @@ use arrayvec::ArrayVec; use gdbstub::arch::Arch; use gdbstub::common::{Signal, Tid}; use gdbstub::stub::{BaseStopReason, MultiThreadStopReason}; +use gdbstub::target::ext::base::BaseOps; use gdbstub::target::ext::base::multithread::{ MultiThreadBase, MultiThreadResume, MultiThreadResumeOps, MultiThreadSingleStep, MultiThreadSingleStepOps, }; -use gdbstub::target::ext::base::BaseOps; use gdbstub::target::ext::breakpoints::{ Breakpoints, BreakpointsOps, HwBreakpoint, HwBreakpointOps, SwBreakpoint, SwBreakpointOps, }; use gdbstub::target::ext::thread_extra_info::{ThreadExtraInfo, ThreadExtraInfoOps}; use gdbstub::target::{Target, TargetError, TargetResult}; #[cfg(target_arch = "aarch64")] -use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs; -#[cfg(target_arch = "aarch64")] use gdbstub_arch::aarch64::AArch64 as GdbArch; -#[cfg(target_arch = "x86_64")] -use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs; +#[cfg(target_arch = "aarch64")] +use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs; #[cfg(target_arch = "x86_64")] use gdbstub_arch::x86::X86_64_SSE as GdbArch; +#[cfg(target_arch = "x86_64")] +use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs; use kvm_ioctls::VcpuFd; use vm_memory::{Bytes, GuestAddress, GuestMemoryError}; use super::arch; +use crate::arch::GUEST_PAGE_SIZE; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::vcpu::VcpuError as AarchVcpuError; -use crate::arch::GUEST_PAGE_SIZE; use crate::logger::{error, info}; use crate::utils::u64_to_usize; use crate::vstate::vcpu::VcpuSendEventError; diff --git a/src/vmm/src/io_uring/mod.rs b/src/vmm/src/io_uring/mod.rs index 0de1abbf4eb..1c2ca1bfc6e 100644 --- a/src/vmm/src/io_uring/mod.rs +++ b/src/vmm/src/io_uring/mod.rs @@ -15,7 +15,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use generated::io_uring_params; use operation::{Cqe, FixedFd, OpCode, Operation}; -use probe::{ProbeWrapper, PROBE_LEN}; +use probe::{PROBE_LEN, ProbeWrapper}; pub use queue::completion::CQueueError; use queue::completion::CompletionQueue; pub use queue::submission::SQueueError; diff --git a/src/vmm/src/io_uring/operation/mod.rs b/src/vmm/src/io_uring/operation/mod.rs index 751a1ef835f..6307d1413c0 100644 --- a/src/vmm/src/io_uring/operation/mod.rs +++ b/src/vmm/src/io_uring/operation/mod.rs @@ -12,7 +12,7 @@ use std::fmt::{self, Debug}; pub use cqe::Cqe; pub(crate) use sqe::Sqe; -use crate::io_uring::generated::{self, io_uring_sqe, IOSQE_FIXED_FILE_BIT}; +use crate::io_uring::generated::{self, IOSQE_FIXED_FILE_BIT, io_uring_sqe}; /// The index of a registered fd. pub type FixedFd = u32; diff --git a/src/vmm/src/io_uring/queue/completion.rs b/src/vmm/src/io_uring/queue/completion.rs index b225af7fa0e..1af8ef3ed71 100644 --- a/src/vmm/src/io_uring/queue/completion.rs +++ b/src/vmm/src/io_uring/queue/completion.rs @@ -8,7 +8,7 @@ use std::sync::atomic::Ordering; use vm_memory::{Bytes, VolatileMemory, VolatileMemoryError}; -use super::mmap::{mmap, MmapError}; +use super::mmap::{MmapError, mmap}; use crate::io_uring::generated; use crate::io_uring::operation::Cqe; use crate::vstate::memory::MmapRegion; diff --git a/src/vmm/src/io_uring/queue/submission.rs b/src/vmm/src/io_uring/queue/submission.rs index 4cef656a30c..db308e63a54 100644 --- a/src/vmm/src/io_uring/queue/submission.rs +++ b/src/vmm/src/io_uring/queue/submission.rs @@ -11,7 +11,7 @@ use std::sync::atomic::Ordering; use vm_memory::{VolatileMemory, VolatileMemoryError}; use vmm_sys_util::syscall::SyscallReturnCode; -use super::mmap::{mmap, MmapError}; +use super::mmap::{MmapError, mmap}; use crate::io_uring::generated; use crate::io_uring::operation::Sqe; use crate::vstate::memory::{Bytes, MmapRegion}; @@ -99,11 +99,10 @@ impl SubmissionQueue { } // retrieve and populate the sqe - if let Err(err) = self - .sqes - .as_volatile_slice() - .write_obj(sqe.0, (tail as usize) * mem::size_of::()) - { + if let Err(err) = self.sqes.as_volatile_slice().write_obj( + sqe.0, + (tail as usize) * mem::size_of::(), + ) { return Err((SQueueError::VolatileMemory(err), sqe.user_data())); } @@ -162,12 +161,21 @@ impl SubmissionQueue { let sqe_ring_size = (params.sq_off.array as usize) + (params.sq_entries as usize) * mem::size_of::(); - let sqe_ring = mmap(sqe_ring_size, io_uring_fd, generated::IORING_OFF_SQ_RING.into())?; + let sqe_ring = mmap( + sqe_ring_size, + io_uring_fd, + generated::IORING_OFF_SQ_RING.into(), + )?; // map the SQEs. - let sqes_array_size = (params.sq_entries as usize) * mem::size_of::(); + let sqes_array_size = + (params.sq_entries as usize) * mem::size_of::(); - let sqes = mmap(sqes_array_size, io_uring_fd, generated::IORING_OFF_SQES.into())?; + let sqes = mmap( + sqes_array_size, + io_uring_fd, + generated::IORING_OFF_SQES.into(), + )?; Ok((sqe_ring, sqes)) } diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 9be5ba53d02..492077df068 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -137,12 +137,12 @@ use crate::device_manager::legacy::PortIODeviceManager; use crate::device_manager::mmio::MMIODeviceManager; use crate::devices::legacy::{IER_RDA_BIT, IER_RDA_OFFSET}; use crate::devices::virtio::balloon::{ - Balloon, BalloonConfig, BalloonError, BalloonStats, BALLOON_DEV_ID, + BALLOON_DEV_ID, Balloon, BalloonConfig, BalloonError, BalloonStats, }; use crate::devices::virtio::block::device::Block; use crate::devices::virtio::net::Net; use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_NET}; -use crate::logger::{error, info, warn, MetricsError, METRICS}; +use crate::logger::{METRICS, MetricsError, error, info, warn}; use crate::persist::{MicrovmState, MicrovmStateError, VmInfo}; use crate::rate_limiter::BucketUpdate; use crate::snapshot::Persist; diff --git a/src/vmm/src/logger/metrics.rs b/src/vmm/src/logger/metrics.rs index a911a53e8a9..e793495e1f1 100644 --- a/src/vmm/src/logger/metrics.rs +++ b/src/vmm/src/logger/metrics.rs @@ -68,7 +68,7 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Mutex, OnceLock}; use serde::{Serialize, Serializer}; -use utils::time::{get_time_ns, get_time_us, ClockType}; +use utils::time::{ClockType, get_time_ns, get_time_us}; use super::FcLineWriter; use crate::devices::legacy; @@ -951,8 +951,8 @@ impl FirecrackerMetrics { #[cfg(test)] mod tests { use std::io::{ErrorKind, LineWriter}; - use std::sync::atomic::fence; use std::sync::Arc; + use std::sync::atomic::fence; use std::thread; use vmm_sys_util::tempfile::TempFile; diff --git a/src/vmm/src/logger/mod.rs b/src/vmm/src/logger/mod.rs index 49d765b597b..4bbbf9e19c8 100644 --- a/src/vmm/src/logger/mod.rs +++ b/src/vmm/src/logger/mod.rs @@ -7,16 +7,16 @@ mod logging; mod metrics; -pub use log::{debug, error, info, log_enabled, trace, warn, Level}; +pub use log::{Level, debug, error, info, log_enabled, trace, warn}; pub use logging::{ - LevelFilter, LevelFilterFromStrError, LoggerConfig, LoggerInitError, LoggerUpdateError, - DEFAULT_INSTANCE_ID, DEFAULT_LEVEL, INSTANCE_ID, LOGGER, + DEFAULT_INSTANCE_ID, DEFAULT_LEVEL, INSTANCE_ID, LOGGER, LevelFilter, LevelFilterFromStrError, + LoggerConfig, LoggerInitError, LoggerUpdateError, }; pub use metrics::{ - IncMetric, LatencyAggregateMetrics, MetricsError, ProcessTimeReporter, SharedIncMetric, - SharedStoreMetric, StoreMetric, METRICS, + IncMetric, LatencyAggregateMetrics, METRICS, MetricsError, ProcessTimeReporter, + SharedIncMetric, SharedStoreMetric, StoreMetric, }; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; /// Alias for `std::io::LineWriter`. pub type FcLineWriter = std::io::LineWriter; diff --git a/src/vmm/src/mmds/data_store.rs b/src/vmm/src/mmds/data_store.rs index 41fe297ab06..518ae7d901a 100644 --- a/src/vmm/src/mmds/data_store.rs +++ b/src/vmm/src/mmds/data_store.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fmt::{Display, Formatter}; use serde::{Deserialize, Serialize}; -use serde_json::{to_vec, Value}; +use serde_json::{Value, to_vec}; use crate::mmds::token::{MmdsTokenError as TokenError, TokenAuthority}; diff --git a/src/vmm/src/mmds/mod.rs b/src/vmm/src/mmds/mod.rs index d4d64e58ffa..cdc0052eb42 100644 --- a/src/vmm/src/mmds/mod.rs +++ b/src/vmm/src/mmds/mod.rs @@ -142,7 +142,7 @@ fn respond_to_request_mmdsv2(mmds: &mut Mmds, request: Request) -> Response { request.http_version(), StatusCode::BadRequest, Body::new(err.to_string()), - ) + ); } }; diff --git a/src/vmm/src/mmds/ns.rs b/src/vmm/src/mmds/ns.rs index 8075df8cb91..8f9a764a7c1 100644 --- a/src/vmm/src/mmds/ns.rs +++ b/src/vmm/src/mmds/ns.rs @@ -13,19 +13,19 @@ use std::sync::{Arc, Mutex}; use utils::time::timestamp_cycles; +use crate::dumbo::pdu::Incomplete; use crate::dumbo::pdu::arp::{ - test_speculative_tpa, ArpError as ArpFrameError, EthIPv4ArpFrame, ETH_IPV4_FRAME_LEN, + ArpError as ArpFrameError, ETH_IPV4_FRAME_LEN, EthIPv4ArpFrame, test_speculative_tpa, }; use crate::dumbo::pdu::ethernet::{ - EthernetError as EthernetFrameError, EthernetFrame, ETHERTYPE_ARP, ETHERTYPE_IPV4, + ETHERTYPE_ARP, ETHERTYPE_IPV4, EthernetError as EthernetFrameError, EthernetFrame, }; use crate::dumbo::pdu::ipv4::{ - test_speculative_dst_addr, IPv4Packet, Ipv4Error as IPv4PacketError, PROTOCOL_TCP, + IPv4Packet, Ipv4Error as IPv4PacketError, PROTOCOL_TCP, test_speculative_dst_addr, }; use crate::dumbo::pdu::tcp::TcpError as TcpSegmentError; -use crate::dumbo::pdu::Incomplete; -use crate::dumbo::tcp::handler::{RecvEvent, TcpIPv4Handler, WriteEvent, WriteNextError}; use crate::dumbo::tcp::NextSegmentStatus; +use crate::dumbo::tcp::handler::{RecvEvent, TcpIPv4Handler, WriteEvent, WriteNextError}; use crate::logger::{IncMetric, METRICS}; use crate::mmds::data_store::Mmds; use crate::utils::net::mac::MacAddr; diff --git a/src/vmm/src/mmds/persist.rs b/src/vmm/src/mmds/persist.rs index 82feff79bc8..10b09c4f7ae 100644 --- a/src/vmm/src/mmds/persist.rs +++ b/src/vmm/src/mmds/persist.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use super::ns::MmdsNetworkStack; use crate::mmds::data_store::Mmds; use crate::snapshot::Persist; -use crate::utils::net::mac::{MacAddr, MAC_ADDR_LEN}; +use crate::utils::net::mac::{MAC_ADDR_LEN, MacAddr}; /// State of a MmdsNetworkStack. #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/vmm/src/mmds/token.rs b/src/vmm/src/mmds/token.rs index c1d211141cc..64c65e9015d 100644 --- a/src/vmm/src/mmds/token.rs +++ b/src/vmm/src/mmds/token.rs @@ -12,7 +12,7 @@ use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Nonce}; use base64::Engine; use bincode::{DefaultOptions, Error as BincodeError, Options}; use serde::{Deserialize, Serialize}; -use utils::time::{get_time_ms, ClockType}; +use utils::time::{ClockType, get_time_ms}; /// Length of initialization vector. pub const IV_LEN: usize = 12; diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index d62ffc84600..91a29909590 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -21,9 +21,9 @@ use crate::arch::aarch64::vcpu::{get_manufacturer_id_from_host, get_manufacturer use crate::builder::{self, BuildMicrovmFromSnapshotError}; use crate::cpu_config::templates::StaticCpuTemplate; #[cfg(target_arch = "x86_64")] -use crate::cpu_config::x86_64::cpuid::common::get_vendor_id_from_host; -#[cfg(target_arch = "x86_64")] use crate::cpu_config::x86_64::cpuid::CpuidTrait; +#[cfg(target_arch = "x86_64")] +use crate::cpu_config::x86_64::cpuid::common::get_vendor_id_from_host; use crate::device_manager::persist::{ACPIDeviceManagerState, DevicePersistError, DeviceStates}; use crate::logger::{info, warn}; use crate::resources::VmResources; @@ -42,7 +42,7 @@ use crate::vstate::memory::{ }; use crate::vstate::vcpu::{VcpuSendEventError, VcpuState}; use crate::vstate::vm::VmState; -use crate::{mem_size_mib, vstate, EventManager, Vmm, VmmError}; +use crate::{EventManager, Vmm, VmmError, mem_size_mib, vstate}; /// Holds information related to the VM that is not part of VmState. #[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] @@ -644,11 +644,12 @@ mod tests { use vmm_sys_util::tempfile::TempFile; use super::*; + use crate::Vmm; #[cfg(target_arch = "x86_64")] use crate::builder::tests::insert_vmgenid_device; use crate::builder::tests::{ - default_kernel_cmdline, default_vmm, insert_balloon_device, insert_block_devices, - insert_net_device, insert_vsock_device, CustomBlockConfig, + CustomBlockConfig, default_kernel_cmdline, default_vmm, insert_balloon_device, + insert_block_devices, insert_net_device, insert_vsock_device, }; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; @@ -658,7 +659,6 @@ mod tests { use crate::vmm_config::net::NetworkInterfaceConfig; use crate::vmm_config::vsock::tests::default_config; use crate::vstate::memory::GuestMemoryRegionState; - use crate::Vmm; fn default_vmm_with_devices() -> Vmm { let mut event_manager = EventManager::new().expect("Cannot create EventManager"); diff --git a/src/vmm/src/rate_limiter/persist.rs b/src/vmm/src/rate_limiter/persist.rs index 671e99ede38..fea5e9a8742 100644 --- a/src/vmm/src/rate_limiter/persist.rs +++ b/src/vmm/src/rate_limiter/persist.rs @@ -132,14 +132,18 @@ mod tests { let restored_rate_limiter = RateLimiter::restore((), &rate_limiter.save()).expect("Unable to restore rate limiter"); - assert!(rate_limiter - .ops() - .unwrap() - .partial_eq(restored_rate_limiter.ops().unwrap())); - assert!(rate_limiter - .bandwidth() - .unwrap() - .partial_eq(restored_rate_limiter.bandwidth().unwrap())); + assert!( + rate_limiter + .ops() + .unwrap() + .partial_eq(restored_rate_limiter.ops().unwrap()) + ); + assert!( + rate_limiter + .bandwidth() + .unwrap() + .partial_eq(restored_rate_limiter.bandwidth().unwrap()) + ); assert_eq!( restored_rate_limiter.timer_fd.get_state(), TimerState::Disarmed @@ -151,14 +155,18 @@ mod tests { let restored_rate_limiter = RateLimiter::restore((), &rate_limiter.save()).expect("Unable to restore rate limiter"); - assert!(rate_limiter - .ops() - .unwrap() - .partial_eq(restored_rate_limiter.ops().unwrap())); - assert!(rate_limiter - .bandwidth() - .unwrap() - .partial_eq(restored_rate_limiter.bandwidth().unwrap())); + assert!( + rate_limiter + .ops() + .unwrap() + .partial_eq(restored_rate_limiter.ops().unwrap()) + ); + assert!( + rate_limiter + .bandwidth() + .unwrap() + .partial_eq(restored_rate_limiter.bandwidth().unwrap()) + ); assert_eq!( restored_rate_limiter.timer_fd.get_state(), TimerState::Disarmed @@ -169,14 +177,18 @@ mod tests { let restored_rate_limiter = RateLimiter::restore((), &rate_limiter.save()).expect("Unable to restore rate limiter"); - assert!(rate_limiter - .ops() - .unwrap() - .partial_eq(restored_rate_limiter.ops().unwrap())); - assert!(rate_limiter - .bandwidth() - .unwrap() - .partial_eq(restored_rate_limiter.bandwidth().unwrap())); + assert!( + rate_limiter + .ops() + .unwrap() + .partial_eq(restored_rate_limiter.ops().unwrap()) + ); + assert!( + rate_limiter + .bandwidth() + .unwrap() + .partial_eq(restored_rate_limiter.bandwidth().unwrap()) + ); // Test serialization. let mut mem = vec![0; 4096]; @@ -184,13 +196,17 @@ mod tests { let restored_rate_limiter = RateLimiter::restore((), &Snapshot::deserialize(&mut mem.as_slice()).unwrap()).unwrap(); - assert!(rate_limiter - .ops() - .unwrap() - .partial_eq(restored_rate_limiter.ops().unwrap())); - assert!(rate_limiter - .bandwidth() - .unwrap() - .partial_eq(restored_rate_limiter.bandwidth().unwrap())); + assert!( + rate_limiter + .ops() + .unwrap() + .partial_eq(restored_rate_limiter.ops().unwrap()) + ); + assert!( + rate_limiter + .bandwidth() + .unwrap() + .partial_eq(restored_rate_limiter.bandwidth().unwrap()) + ); } } diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 024f8833b78..113c24cad51 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -24,7 +24,7 @@ use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{ HugePageConfig, MachineConfig, MachineConfigError, MachineConfigUpdate, }; -use crate::vmm_config::metrics::{init_metrics, MetricsConfig, MetricsConfigError}; +use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics}; use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; use crate::vmm_config::net::*; use crate::vmm_config::vsock::*; @@ -501,6 +501,7 @@ mod tests { use vmm_sys_util::tempfile::TempFile; use super::*; + use crate::HTTP_MAX_PAYLOAD_SIZE; use crate::cpu_config::templates::{CpuTemplateType, StaticCpuTemplate}; use crate::devices::virtio::balloon::Balloon; use crate::devices::virtio::block::virtio::VirtioBlockError; @@ -508,6 +509,7 @@ mod tests { use crate::devices::virtio::vsock::VSOCK_DEV_ID; use crate::resources::VmResources; use crate::utils::net::mac::MacAddr; + use crate::vmm_config::RateLimiterConfig; use crate::vmm_config::boot_source::{ BootConfig, BootSource, BootSourceConfig, DEFAULT_KERNEL_CMDLINE, }; @@ -515,8 +517,6 @@ mod tests { use crate::vmm_config::machine_config::{HugePageConfig, MachineConfig, MachineConfigError}; use crate::vmm_config::net::{NetBuilder, NetworkInterfaceConfig}; use crate::vmm_config::vsock::tests::default_config; - use crate::vmm_config::RateLimiterConfig; - use crate::HTTP_MAX_PAYLOAD_SIZE; fn default_net_cfg() -> NetworkInterfaceConfig { NetworkInterfaceConfig { diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 82993fcafea..3aca3e2a6f0 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -5,15 +5,16 @@ use std::fmt::{self, Debug}; use std::sync::{Arc, Mutex, MutexGuard}; use serde_json::Value; -use utils::time::{get_time_us, ClockType}; +use utils::time::{ClockType, get_time_us}; use super::builder::build_and_boot_microvm; use super::persist::{create_snapshot, restore_from_snapshot}; use super::resources::VmResources; use super::{Vmm, VmmError}; +use crate::EventManager; use crate::builder::StartMicrovmError; use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; -use crate::logger::{info, warn, LoggerConfig, *}; +use crate::logger::{LoggerConfig, info, warn, *}; use crate::mmds::data_store::{self, Mmds}; use crate::persist::{CreateSnapshotError, RestoreFromSnapshotError, VmInfo}; use crate::resources::VmmConfig; @@ -35,7 +36,6 @@ use crate::vmm_config::net::{ use crate::vmm_config::snapshot::{CreateSnapshotParams, LoadSnapshotParams, SnapshotType}; use crate::vmm_config::vsock::{VsockConfigError, VsockDeviceConfig}; use crate::vmm_config::{self, RateLimiterUpdate}; -use crate::EventManager; /// This enum represents the public interface of the VMM. Each action contains various /// bits of information (ids, paths, etc.). @@ -856,12 +856,12 @@ mod tests { use std::path::PathBuf; use super::*; + use crate::HTTP_MAX_PAYLOAD_SIZE; use crate::builder::tests::default_vmm; use crate::devices::virtio::block::CacheType; use crate::mmds::data_store::MmdsVersion; use crate::seccomp::BpfThreadMap; use crate::vmm_config::snapshot::{MemBackendConfig, MemBackendType}; - use crate::HTTP_MAX_PAYLOAD_SIZE; fn default_preboot<'a>( vm_resources: &'a mut VmResources, diff --git a/src/vmm/src/signal_handler.rs b/src/vmm/src/signal_handler.rs index ac4befcb3d1..3b6162c7e4c 100644 --- a/src/vmm/src/signal_handler.rs +++ b/src/vmm/src/signal_handler.rs @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use libc::{ - c_int, c_void, siginfo_t, SIGBUS, SIGHUP, SIGILL, SIGPIPE, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ, + SIGBUS, SIGHUP, SIGILL, SIGPIPE, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ, c_int, c_void, siginfo_t, }; use log::error; -use crate::logger::{IncMetric, StoreMetric, METRICS}; -use crate::utils::signal::register_signal_handler; use crate::FcExitCode; +use crate::logger::{IncMetric, METRICS, StoreMetric}; +use crate::utils::signal::register_signal_handler; // The offset of `si_syscall` (offending syscall identifier) within the siginfo structure // expressed as an `(u)int*`. diff --git a/src/vmm/src/vmm_config/balloon.rs b/src/vmm/src/vmm_config/balloon.rs index 5b6f25e8662..6ac2fb34ecf 100644 --- a/src/vmm/src/vmm_config/balloon.rs +++ b/src/vmm/src/vmm_config/balloon.rs @@ -5,8 +5,8 @@ use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; -pub use crate::devices::virtio::balloon::device::BalloonStats; pub use crate::devices::virtio::balloon::BALLOON_DEV_ID; +pub use crate::devices::virtio::balloon::device::BalloonStats; use crate::devices::virtio::balloon::{Balloon, BalloonConfig}; type MutexBalloon = Arc>; diff --git a/src/vmm/src/vmm_config/drive.rs b/src/vmm/src/vmm_config/drive.rs index cdfc732d48b..9e301eff751 100644 --- a/src/vmm/src/vmm_config/drive.rs +++ b/src/vmm/src/vmm_config/drive.rs @@ -8,10 +8,10 @@ use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; use super::RateLimiterConfig; +use crate::VmmError; use crate::devices::virtio::block::device::Block; pub use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::block::{BlockError, CacheType}; -use crate::VmmError; /// Errors associated with the operations allowed on a drive. #[derive(Debug, thiserror::Error, displaydoc::Display)] @@ -513,15 +513,19 @@ mod tests { ); // Get None. - assert!(block_devs - .get_index_of_drive_id(&String::from("foo")) - .is_none()); + assert!( + block_devs + .get_index_of_drive_id(&String::from("foo")) + .is_none() + ); // Test several update cases using dummy_block_device_2. // Validate `dummy_block_device_2` is already in the list - assert!(block_devs - .get_index_of_drive_id(&dummy_block_device_2.drive_id) - .is_some()); + assert!( + block_devs + .get_index_of_drive_id(&dummy_block_device_2.drive_id) + .is_some() + ); // Update OK. dummy_block_device_2.is_read_only = Some(true); block_devs.insert(dummy_block_device_2.clone()).unwrap(); diff --git a/src/vmm/src/vmm_config/instance_info.rs b/src/vmm/src/vmm_config/instance_info.rs index 67fd335deaa..cd5b44f30ba 100644 --- a/src/vmm/src/vmm_config/instance_info.rs +++ b/src/vmm/src/vmm_config/instance_info.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use std::fmt::{self, Display, Formatter}; -use serde::{ser, Serialize}; +use serde::{Serialize, ser}; /// Enumerates microVM runtime states. #[derive(Clone, Debug, Default, PartialEq, Eq)] diff --git a/src/vmm/src/vmm_config/net.rs b/src/vmm/src/vmm_config/net.rs index 8ece4e7e494..f1413368090 100644 --- a/src/vmm/src/vmm_config/net.rs +++ b/src/vmm/src/vmm_config/net.rs @@ -8,9 +8,9 @@ use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; use super::RateLimiterConfig; +use crate::VmmError; use crate::devices::virtio::net::{Net, TapError}; use crate::utils::net::mac::MacAddr; -use crate::VmmError; /// This struct represents the strongly typed equivalent of the json body from net iface /// related requests. diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index c7d29b449c5..7c44cfb91cb 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -3,12 +3,12 @@ use kvm_bindings::KVM_API_VERSION; #[cfg(target_arch = "x86_64")] -use kvm_bindings::{CpuId, MsrList, KVM_MAX_CPUID_ENTRIES}; +use kvm_bindings::{CpuId, KVM_MAX_CPUID_ENTRIES, MsrList}; use kvm_ioctls::Kvm as KvmFd; use serde::{Deserialize, Serialize}; #[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::xstate::{request_dynamic_xstate_features, XstateError}; +use crate::arch::x86_64::xstate::{XstateError, request_dynamic_xstate_features}; use crate::cpu_config::templates::KvmCapability; use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; @@ -215,11 +215,15 @@ pub(crate) mod tests { ]; let combined_caps = Kvm::combine_capabilities(&additional_capabilities); - assert!(combined_caps - .iter() - .any(|c| *c == kvm_bindings::KVM_CAP_IOMMU)); - assert!(!combined_caps - .iter() - .any(|c| *c == kvm_bindings::KVM_CAP_IOEVENTFD)); + assert!( + combined_caps + .iter() + .any(|c| *c == kvm_bindings::KVM_CAP_IOMMU) + ); + assert!( + !combined_caps + .iter() + .any(|c| *c == kvm_bindings::KVM_CAP_IOEVENTFD) + ); } } diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 228c8b8f062..e0f47848684 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -11,20 +11,20 @@ use std::sync::Arc; use libc::c_int; use serde::{Deserialize, Serialize}; -pub use vm_memory::bitmap::{AtomicBitmap, Bitmap, BitmapSlice, BS}; +pub use vm_memory::bitmap::{AtomicBitmap, BS, Bitmap, BitmapSlice}; pub use vm_memory::mmap::MmapRegionBuilder; use vm_memory::mmap::{MmapRegionError, NewBitmap}; pub use vm_memory::{ - address, Address, ByteValued, Bytes, FileOffset, GuestAddress, GuestMemory, GuestMemoryRegion, - GuestUsize, MemoryRegionAddress, MmapRegion, + Address, ByteValued, Bytes, FileOffset, GuestAddress, GuestMemory, GuestMemoryRegion, + GuestUsize, MemoryRegionAddress, MmapRegion, address, }; use vm_memory::{Error as VmMemoryError, GuestMemoryError, WriteVolatile}; use vmm_sys_util::errno; +use crate::DirtyBitmap; use crate::arch::arch_memory_regions; use crate::utils::{get_page_size, u64_to_usize}; use crate::vmm_config::machine_config::HugePageConfig; -use crate::DirtyBitmap; /// Type of GuestMemoryMmap. pub type GuestMemoryMmap = vm_memory::GuestMemoryMmap>; @@ -189,7 +189,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { offset = match offset.checked_add(size as u64) { None => return Err(MemoryError::OffsetTooLarge), Some(new_off) if new_off >= i64::MAX as u64 => { - return Err(MemoryError::OffsetTooLarge) + return Err(MemoryError::OffsetTooLarge); } Some(new_off) => new_off, }; diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs index c5d3f4dbb8b..98972c796d2 100644 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ b/src/vmm/src/vstate/vcpu/aarch64.rs @@ -8,20 +8,20 @@ use std::fmt::{Debug, Write}; use kvm_bindings::{ - kvm_mp_state, kvm_vcpu_init, KVM_ARM_VCPU_POWER_OFF, KVM_ARM_VCPU_PSCI_0_2, KVM_ARM_VCPU_SVE, + KVM_ARM_VCPU_POWER_OFF, KVM_ARM_VCPU_PSCI_0_2, KVM_ARM_VCPU_SVE, kvm_mp_state, kvm_vcpu_init, }; use kvm_ioctls::*; use serde::{Deserialize, Serialize}; +use crate::arch::EntryPoint; use crate::arch::aarch64::regs::{Aarch64RegisterVec, KVM_REG_ARM64_SVE_VLS}; use crate::arch::aarch64::vcpu::{ - get_all_registers, get_all_registers_ids, get_mpidr, get_mpstate, get_registers, set_mpstate, - set_register, setup_boot_regs, VcpuError as ArchError, + VcpuError as ArchError, get_all_registers, get_all_registers_ids, get_mpidr, get_mpstate, + get_registers, set_mpstate, set_register, setup_boot_regs, }; -use crate::arch::EntryPoint; use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; use crate::cpu_config::templates::CpuConfiguration; -use crate::logger::{error, IncMetric, METRICS}; +use crate::logger::{IncMetric, METRICS, error}; use crate::vcpu::{VcpuConfig, VcpuError}; use crate::vstate::kvm::OptionalCapabilities; use crate::vstate::memory::{Address, GuestMemoryMmap}; @@ -307,15 +307,15 @@ mod tests { use vm_memory::GuestAddress; use super::*; - use crate::arch::aarch64::regs::Aarch64RegisterRef; use crate::arch::BootProtocol; + use crate::arch::aarch64::regs::Aarch64RegisterRef; use crate::cpu_config::aarch64::CpuConfiguration; use crate::cpu_config::templates::RegisterValueFilter; use crate::vcpu::VcpuConfig; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; - use crate::vstate::vm::tests::setup_vm_with_memory; use crate::vstate::vm::Vm; + use crate::vstate::vm::tests::setup_vm_with_memory; fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu/mod.rs index 4fb430a9c39..a04177cd938 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu/mod.rs @@ -8,8 +8,8 @@ use std::cell::Cell; #[cfg(feature = "gdb")] use std::os::fd::AsRawFd; -use std::sync::atomic::{fence, Ordering}; -use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError}; +use std::sync::atomic::{Ordering, fence}; +use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel}; use std::sync::{Arc, Barrier}; use std::{fmt, io, thread}; @@ -22,15 +22,15 @@ use log::{error, info, warn}; use vmm_sys_util::errno; use vmm_sys_util::eventfd::EventFd; +use crate::FcExitCode; use crate::cpu_config::templates::{CpuConfiguration, GuestConfigError}; #[cfg(feature = "gdb")] -use crate::gdb::target::{get_raw_tid, GdbTargetError}; +use crate::gdb::target::{GdbTargetError, get_raw_tid}; use crate::logger::{IncMetric, METRICS}; use crate::seccomp::{BpfProgram, BpfProgramRef}; -use crate::utils::signal::{register_signal_handler, sigrtmin, Killable}; +use crate::utils::signal::{Killable, register_signal_handler, sigrtmin}; use crate::utils::sm::StateMachine; use crate::vstate::vm::Vm; -use crate::FcExitCode; /// Module with aarch64 vCPU implementation. #[cfg(target_arch = "aarch64")] @@ -780,18 +780,18 @@ pub(crate) mod tests { use vmm_sys_util::errno; use super::*; + use crate::RECV_TIMEOUT_SEC; use crate::arch::{BootProtocol, EntryPoint}; use crate::builder::StartMicrovmError; - use crate::devices::bus::DummyDevice; use crate::devices::BusDevice; + use crate::devices::bus::DummyDevice; use crate::seccomp::get_empty_filters; use crate::utils::signal::validate_signal_num; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::VcpuError as EmulationError; - use crate::vstate::vm::tests::setup_vm_with_memory; use crate::vstate::vm::Vm; - use crate::RECV_TIMEOUT_SEC; + use crate::vstate::vm::tests::setup_vm_with_memory; #[test] fn test_handle_kvm_exit() { diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 9871bd8ccc3..d4d6df12c16 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -9,20 +9,20 @@ use std::collections::BTreeMap; use std::fmt::Debug; use kvm_bindings::{ - kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, - kvm_xsave, kvm_xsave2, CpuId, Msrs, Xsave, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES, + CpuId, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES, Msrs, Xsave, kvm_debugregs, kvm_lapic_state, + kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, kvm_xsave, kvm_xsave2, }; use kvm_ioctls::{VcpuExit, VcpuFd}; use log::{error, warn}; use serde::{Deserialize, Serialize}; use vmm_sys_util::fam::{self, FamStruct}; +use crate::arch::EntryPoint; use crate::arch::x86_64::generated::msr_index::{MSR_IA32_TSC, MSR_IA32_TSC_DEADLINE}; use crate::arch::x86_64::interrupts; -use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError}; +use crate::arch::x86_64::msr::{MsrError, create_boot_msr_entries}; use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError}; -use crate::arch::EntryPoint; -use crate::cpu_config::x86_64::{cpuid, CpuConfiguration}; +use crate::cpu_config::x86_64::{CpuConfiguration, cpuid}; use crate::logger::{IncMetric, METRICS}; use crate::vstate::memory::GuestMemoryMmap; use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation}; @@ -796,16 +796,16 @@ mod tests { use vm_memory::GuestAddress; use super::*; - use crate::arch::x86_64::cpu_model::CpuModel; use crate::arch::BootProtocol; + use crate::arch::x86_64::cpu_model::CpuModel; use crate::cpu_config::templates::{ CpuConfiguration, CpuTemplateType, CustomCpuTemplate, GetCpuTemplate, GuestConfigError, StaticCpuTemplate, }; use crate::cpu_config::x86_64::cpuid::{Cpuid, CpuidEntry, CpuidKey}; use crate::vstate::kvm::Kvm; - use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; use crate::vstate::vm::Vm; + use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; impl Default for VcpuState { fn default() -> Self { @@ -1091,9 +1091,11 @@ mod tests { / u32::try_from(TSC_KHZ_TOL_DENOMINATOR).unwrap() / 2, ); - assert!(!vcpu - .is_tsc_scaling_required(state.tsc_khz.unwrap()) - .unwrap()); + assert!( + !vcpu + .is_tsc_scaling_required(state.tsc_khz.unwrap()) + .unwrap() + ); } { @@ -1105,9 +1107,10 @@ mod tests { / u32::try_from(TSC_KHZ_TOL_DENOMINATOR).unwrap() * 2, ); - assert!(vcpu - .is_tsc_scaling_required(state.tsc_khz.unwrap()) - .unwrap()); + assert!( + vcpu.is_tsc_scaling_required(state.tsc_khz.unwrap()) + .unwrap() + ); } { diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/vstate/vm/aarch64.rs index 6aee3d8e609..5f22e1432ee 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/vstate/vm/aarch64.rs @@ -5,8 +5,8 @@ use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; use super::VmError; -use crate::arch::aarch64::gic::GicState; use crate::Kvm; +use crate::arch::aarch64::gic::GicState; /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm/mod.rs index 5f4c7bb53c5..49c65bd92ed 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm/mod.rs @@ -5,7 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; +use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; @@ -21,8 +21,8 @@ mod arch; pub use arch::{ArchVm as Vm, ArchVmError, VmState}; -use crate::vstate::vcpu::VcpuError; use crate::Vcpu; +use crate::vstate::vcpu::VcpuError; /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/vstate/vm/x86_64.rs index ef190b59036..69bad36c09e 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/vstate/vm/x86_64.rs @@ -4,8 +4,8 @@ use std::fmt; use kvm_bindings::{ - kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, MsrList, KVM_CLOCK_TSC_STABLE, - KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, + KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, + KVM_PIT_SPEAKER_DUMMY, MsrList, kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, }; use kvm_ioctls::{Cap, VmFd}; use serde::{Deserialize, Serialize}; @@ -231,8 +231,8 @@ mod tests { }; use crate::snapshot::Snapshot; - use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; use crate::vstate::vm::VmState; + use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory}; #[cfg(target_arch = "x86_64")] #[test] diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index a66f29e7f55..bb0ac5f3240 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -7,7 +7,7 @@ use std::time::Duration; use vmm::builder::build_and_boot_microvm; use vmm::devices::virtio::block::CacheType; -use vmm::persist::{snapshot_state_sanity_check, MicrovmState, MicrovmStateError, VmInfo}; +use vmm::persist::{MicrovmState, MicrovmStateError, VmInfo, snapshot_state_sanity_check}; use vmm::resources::VmResources; use vmm::rpc_interface::{ LoadSnapshotError, PrebootApiController, RuntimeApiController, VmmAction, VmmActionError, From 6cee4a8fb8cff0faf70ee587ffe358f1f079070a Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Thu, 13 Mar 2025 09:38:21 +0000 Subject: [PATCH 355/464] chore(clippy): fix unneeded late initialization The re-formatting made clippy aware of this unneeded late initialization. Let's fix it. Signed-off-by: Riccardo Mancini --- src/vmm/src/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 499d64cae6c..476bbc365c9 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -655,9 +655,8 @@ where { use self::StartMicrovmError::{InitrdLoad, InitrdRead}; - let size: usize; // Get the image size - match image.seek(SeekFrom::End(0)) { + let size = match image.seek(SeekFrom::End(0)) { Err(err) => return Err(InitrdRead(err)), Ok(0) => { return Err(InitrdRead(io::Error::new( @@ -665,7 +664,7 @@ where "Initrd image seek returned a size of zero", ))); } - Ok(s) => size = u64_to_usize(s), + Ok(s) => u64_to_usize(s), }; // Go back to the image start image.seek(SeekFrom::Start(0)).map_err(InitrdRead)?; From e7f60511f761e4c622ee0609a71c7b76d3925b6c Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Thu, 13 Mar 2025 10:57:53 +0000 Subject: [PATCH 356/464] chore: Ignore paste unmaintained warning While gdbstub moves away from paste as a dependency we will ignore this warning. Signed-off-by: Jack Thomson --- .cargo/audit.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.cargo/audit.toml b/.cargo/audit.toml index b28486dffb9..6b623cb495c 100644 --- a/.cargo/audit.toml +++ b/.cargo/audit.toml @@ -1 +1,7 @@ [advisories] +# The `paste` dependency is transitively included via `gdbstub`. +# While the crate is archived/unmaintained, the author considers it feature-complete +# and functionally stable. gdbstub will be update once they migrate +# to an alternative solution. +# See https://github.com/daniel5151/gdbstub/issues/168 +ignore = ["RUSTSEC-2024-0436"] From 0d9904cbc31da058852ad63eec7248af36d6eb3f Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 10:33:55 +0000 Subject: [PATCH 357/464] refactor(vmm): Reorder normalization of feature info leaf Reorder normalization from lower bits to higher and from EAX to EDX. No functional change. Signed-off-by: Takahiro Itazuri --- .../src/cpu_config/x86_64/cpuid/normalize.rs | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index cec8aad2f4c..be35f3ad757 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -237,41 +237,12 @@ impl super::Cpuid { .get_mut(&CpuidKey::leaf(0x1)) .ok_or(FeatureInformationError::MissingLeaf1)?; - // A value of 1 indicates the processor supports the performance and debug feature - // indication MSR IA32_PERF_CAPABILITIES. - // - // pdcm: 15, - set_bit(&mut leaf_1.result.ecx, ECX_PDCM_BITINDEX, false); - - // A value of 1 indicates that the processor’s local APIC timer supports one-shot - // operation using a TSC deadline value. - // - // tsc_deadline: 24, - set_bit(&mut leaf_1.result.ecx, ECX_TSC_DEADLINE_BITINDEX, true); - - // Hypervisor bit - set_bit(&mut leaf_1.result.ecx, ECX_HYPERVISOR_BITINDEX, true); - - // Initial APIC ID. - // - // The 8-bit initial APIC ID in EBX[31:24] is replaced by the 32-bit x2APIC ID, - // available in Leaf 0BH and Leaf 1FH. - // - // initial_apic_id: 24..32, - set_range(&mut leaf_1.result.ebx, 24..32, u32::from(cpu_index)) - .map_err(FeatureInformationError::InitialApicId)?; - // CLFLUSH line size (Value ∗ 8 = cache line size in bytes; used also by CLFLUSHOPT). // // clflush: 8..16, set_range(&mut leaf_1.result.ebx, 8..16, EBX_CLFLUSH_CACHELINE) .map_err(FeatureInformationError::Clflush)?; - let max_cpus_per_package = u32::from( - get_max_cpus_per_package(cpu_count) - .map_err(FeatureInformationError::GetMaxCpusPerPackage)?, - ); - // Maximum number of addressable IDs for logical processors in this physical package. // // The nearest power-of-2 integer that is not smaller than EBX[23:16] is the number of @@ -280,9 +251,37 @@ impl super::Cpuid { // CPUID.1.EDX.HTT[bit 28]= 1. // // max_addressable_logical_processor_ids: 16..24, + let max_cpus_per_package = u32::from( + get_max_cpus_per_package(cpu_count) + .map_err(FeatureInformationError::GetMaxCpusPerPackage)?, + ); set_range(&mut leaf_1.result.ebx, 16..24, max_cpus_per_package) .map_err(FeatureInformationError::SetMaxCpusPerPackage)?; + // Initial APIC ID. + // + // The 8-bit initial APIC ID in EBX[31:24] is replaced by the 32-bit x2APIC ID, + // available in Leaf 0BH and Leaf 1FH. + // + // initial_apic_id: 24..32, + set_range(&mut leaf_1.result.ebx, 24..32, u32::from(cpu_index)) + .map_err(FeatureInformationError::InitialApicId)?; + + // A value of 1 indicates the processor supports the performance and debug feature + // indication MSR IA32_PERF_CAPABILITIES. + // + // pdcm: 15, + set_bit(&mut leaf_1.result.ecx, ECX_PDCM_BITINDEX, false); + + // A value of 1 indicates that the processor’s local APIC timer supports one-shot + // operation using a TSC deadline value. + // + // tsc_deadline: 24, + set_bit(&mut leaf_1.result.ecx, ECX_TSC_DEADLINE_BITINDEX, true); + + // Hypervisor bit + set_bit(&mut leaf_1.result.ecx, ECX_HYPERVISOR_BITINDEX, true); + // Max APIC IDs reserved field is Valid. A value of 0 for HTT indicates there is only a // single logical processor in the package and software should assume only a // single APIC ID is reserved. A value of 1 for HTT indicates the value in From 272fe8f79f808cde410489b6222ed4a4ba6a24c3 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 10:54:33 +0000 Subject: [PATCH 358/464] refactor(vmm): Use CPUID notation used in Intel SDM The CPUID notation is widely used in various Intel docs including SDM. Signed-off-by: Takahiro Itazuri --- .../x86_64/cpuid/intel/normalize.rs | 20 +++--- .../src/cpu_config/x86_64/cpuid/normalize.rs | 69 ++++++++----------- 2 files changed, 35 insertions(+), 54 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 41bc9d3f3f5..0bfc5d89632 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -97,18 +97,16 @@ impl super::IntelCpuid { break; } + // CPUID.04H:EAX[7:5] // Cache Level (Starts at 1) - // - // cache_level: 5..8 let cache_level = get_range(subleaf.result.eax, 5..8); + // CPUID.04H:EAX[25:14] // Maximum number of addressable IDs for logical processors sharing this cache. // - Add one to the return value to get the result. // - The nearest power-of-2 integer that is not smaller than (1 + EAX[25:14]) is the // number of unique initial APIC IDs reserved for addressing different logical // processors sharing this cache. - // - // max_num_addressable_ids_for_logical_processors_sharing_this_cache: 14..26, // We know `cpus_per_core > 0` therefore `cpus_per_core.checked_sub(1).unwrap()` is // always safe. @@ -139,6 +137,7 @@ impl super::IntelCpuid { #[allow(clippy::unwrap_used)] let cores = cpu_count.checked_div(cpus_per_core).unwrap(); + // CPUID.04H:EAX[31:26] // Maximum number of addressable IDs for processor cores in the physical package. // - Add one to the return value to get the result. // - The nearest power-of-2 integer that is not smaller than (1 + EAX[31:26]) is the @@ -146,8 +145,6 @@ impl super::IntelCpuid { // a physical package. Core ID is a subset of bits of the initial APIC ID. // - The returned value is constant for valid initial values in ECX. Valid ECX // values start from 0. - // - // max_num_addressable_ids_for_processor_cores_in_physical_package: 26..32, // Put all the cores in the same socket let sub = u32::from(cores) @@ -168,16 +165,14 @@ impl super::IntelCpuid { .get_mut(&CpuidKey::leaf(0x6)) .ok_or(NormalizeCpuidError::MissingLeaf6)?; + // CPUID.06H:EAX[1] // Intel Turbo Boost Technology available (see description of IA32_MISC_ENABLE[38]). - // - // intel_turbo_boost_technology: 1, set_bit(&mut leaf_6.result.eax, 1, false); + // CPUID.06H:ECX[3] // The processor supports performance-energy bias preference if CPUID.06H:ECX.SETBH[bit 3] // is set and it also implies the presence of a new architectural MSR called // IA32_ENERGY_PERF_BIAS (1B0H). - // - // performance_energy_bias: 3, // Clear X86 EPB feature. No frequency selection in the hypervisor. set_bit(&mut leaf_6.result.ecx, 3, false); @@ -190,8 +185,9 @@ impl super::IntelCpuid { .get_mut(&CpuidKey::subleaf(0x7, 0)) .ok_or(NormalizeCpuidError::MissingLeaf7)?; - // Set FDP_EXCPTN_ONLY bit (bit 6) and ZERO_FCS_FDS bit (bit 13) as recommended in kernel - // doc. These bits are reserved in AMD. + // Set the following bits as recommended in kernel doc. These bits are reserved in AMD. + // - CPUID.07H:EBX[6] (FDP_EXCPTN_ONLY) + // - CPUID.07H:EBX[13] (Deprecates FPU CS and FPU DS values) // https://lore.kernel.org/all/20220322110712.222449-3-pbonzini@redhat.com/ // https://github.com/torvalds/linux/commit/45016721de3c714902c6f475b705e10ae0bdd801 set_bit(&mut leaf_7_0.result.ebx, 6, true); diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index be35f3ad757..18963875813 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -237,20 +237,17 @@ impl super::Cpuid { .get_mut(&CpuidKey::leaf(0x1)) .ok_or(FeatureInformationError::MissingLeaf1)?; - // CLFLUSH line size (Value ∗ 8 = cache line size in bytes; used also by CLFLUSHOPT). - // - // clflush: 8..16, + // CPUID.01H:EBX[15:08] + // CLFLUSH line size (Value * 8 = cache line size in bytes; used also by CLFLUSHOPT). set_range(&mut leaf_1.result.ebx, 8..16, EBX_CLFLUSH_CACHELINE) .map_err(FeatureInformationError::Clflush)?; + // CPUID.01H:EBX[23:16] // Maximum number of addressable IDs for logical processors in this physical package. // // The nearest power-of-2 integer that is not smaller than EBX[23:16] is the number of - // unique initial APIC IDs reserved for addressing different logical - // processors in a physical package. This field is only valid if - // CPUID.1.EDX.HTT[bit 28]= 1. - // - // max_addressable_logical_processor_ids: 16..24, + // unique initial APIC IDs reserved for addressing different logical processors in a + // physical package. This field is only valid if CPUID.1.EDX.HTT[bit 28]= 1. let max_cpus_per_package = u32::from( get_max_cpus_per_package(cpu_count) .map_err(FeatureInformationError::GetMaxCpusPerPackage)?, @@ -258,41 +255,33 @@ impl super::Cpuid { set_range(&mut leaf_1.result.ebx, 16..24, max_cpus_per_package) .map_err(FeatureInformationError::SetMaxCpusPerPackage)?; + // CPUID.01H:EBX[31:24] // Initial APIC ID. // - // The 8-bit initial APIC ID in EBX[31:24] is replaced by the 32-bit x2APIC ID, - // available in Leaf 0BH and Leaf 1FH. - // - // initial_apic_id: 24..32, + // The 8-bit initial APIC ID in EBX[31:24] is replaced by the 32-bit x2APIC ID, available + // in Leaf 0BH and Leaf 1FH. set_range(&mut leaf_1.result.ebx, 24..32, u32::from(cpu_index)) .map_err(FeatureInformationError::InitialApicId)?; - // A value of 1 indicates the processor supports the performance and debug feature - // indication MSR IA32_PERF_CAPABILITIES. - // - // pdcm: 15, + // CPUID.01H:ECX[15] (Mnemonic: PDCM) + // Performance and Debug Capability: A value of 1 indicates the processor supports the + // performance and debug feature indication MSR IA32_PERF_CAPABILITIES. set_bit(&mut leaf_1.result.ecx, ECX_PDCM_BITINDEX, false); - // A value of 1 indicates that the processor’s local APIC timer supports one-shot - // operation using a TSC deadline value. - // - // tsc_deadline: 24, + // CPUID.01H:ECX[24] (Mnemonic: TSC-Deadline) + // A value of 1 indicates that the processor’s local APIC timer supports one-shot operation + // using a TSC deadline value. set_bit(&mut leaf_1.result.ecx, ECX_TSC_DEADLINE_BITINDEX, true); - // Hypervisor bit + // CPUID.01H:ECX[31] (Mnemonic: Hypervisor) set_bit(&mut leaf_1.result.ecx, ECX_HYPERVISOR_BITINDEX, true); + // CPUID.01H:EDX[28] (Mnemonic: HTT) // Max APIC IDs reserved field is Valid. A value of 0 for HTT indicates there is only a - // single logical processor in the package and software should assume only a - // single APIC ID is reserved. A value of 1 for HTT indicates the value in - // CPUID.1.EBX[23:16] (the Maximum number of addressable IDs for logical - // processors in this package) is valid for the package. - // - // htt: 28, - - // A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] - // (the Maximum number of addressable IDs for logical processors in this package) - // is valid for the package + // single logical processor in the package and software should assume only a single APIC ID + // is reserved. A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] (the Maximum + // number of addressable IDs for logical processors in this package) is valid for the + // package. set_bit(&mut leaf_1.result.edx, 28, cpu_count > 1); Ok(()) @@ -316,7 +305,7 @@ impl super::Cpuid { const LEAFBH_INDEX1_APICID: u32 = 7; // The following commit changed the behavior of KVM_GET_SUPPORTED_CPUID to no longer - // include leaf 0xB / sub-leaf 1. + // include CPUID.(EAX=0BH,ECX=1). // https://lore.kernel.org/all/20221027092036.2698180-1-pbonzini@redhat.com/ self.inner_mut() .entry(CpuidKey::subleaf(0xB, 0x1)) @@ -336,8 +325,8 @@ impl super::Cpuid { subleaf.result.eax = 0; subleaf.result.ebx = 0; subleaf.result.ecx = 0; - // EDX bits 31..0 contain x2APIC ID of current logical processor - // x2APIC increases the size of the APIC ID from 8 bits to 32 bits + // CPUID.(EAX=0BH,ECX=N).EDX[31:0] + // x2APIC ID of the current logical processor. subleaf.result.edx = u32::from(cpu_index); subleaf.flags = KvmCpuidFlags::SIGNIFICANT_INDEX; @@ -347,15 +336,15 @@ impl super::Cpuid { // reported at level type = 2." (Intel® 64 Architecture x2APIC // Specification, Ch. 2.8) match index { + // CPUID.(EAX=0BH,ECX=N):EAX[4:0] // Number of bits to shift right on x2APIC ID to get a unique topology ID of the // next level type*. All logical processors with the same // next level ID share current level. // // *Software should use this field (EAX[4:0]) to enumerate processor topology of // the system. - // - // bit_shifts_right_2x_apic_id_unique_topology_id: 0..5 + // CPUID.(EAX=0BH,ECX=N):EBX[15:0] // Number of logical processors at this level type. The number reflects // configuration as shipped by Intel**. // @@ -365,13 +354,11 @@ impl super::Cpuid { // number of logical processors available to BIOS/OS/Applications may be // different from the value of EBX[15:0], depending on // software and platform hardware configurations. - // - // logical_processors: 0..16 + // CPUID.(EAX=0BH,ECX=N):ECX[7:0] // Level number. Same value in ECX input. - // - // level_number: 0..8, + // CPUID.(EAX=0BH,ECX=N):ECX[15:8] // Level type*** // // If an input value n in ECX returns the invalid level-type of 0 in ECX[15:8], @@ -384,8 +371,6 @@ impl super::Cpuid { // - 1: SMT. // - 2: Core. // - 3-255: Reserved. - // - // level_type: 8..16 // Thread Level Topology; index = 0 0 => { From 3acda677f0f5f55cbce387eb9474b3b8f7bec9c9 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 20:38:35 +0000 Subject: [PATCH 359/464] refactor(vmm): Use CPUID notation used in AMD APM The CPUID notation is widely used in various AMD docs including APM. Signed-off-by: Takahiro Itazuri --- .../cpu_config/x86_64/cpuid/amd/normalize.rs | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs index 111960db00a..f0ee9322e12 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs @@ -153,6 +153,7 @@ impl super::AmdCpuid { // On non-AMD hosts this condition may never be true thus this loop may be // indefinite. + // CPUID Fn8000_0001D_EAX_x[4:0] (Field Name: CacheType) // Cache type. Identifies the type of cache. // ```text // Bits Description @@ -162,8 +163,6 @@ impl super::AmdCpuid { // 03h Unified cache // 1Fh-04h Reserved. // ``` - // - // cache_type: 0..4, let cache_type = result.eax & 15; if cache_type == 0 { break; @@ -186,10 +185,9 @@ impl super::AmdCpuid { let leaf_80000001 = self .get_mut(&CpuidKey::leaf(0x80000001)) .ok_or(NormalizeCpuidError::MissingLeaf0x80000001)?; + // CPUID Fn8000_0001_ECX[22] (Field Name: TopologyExtensions) // Topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID // Fn8000_001E_EDX. - // - // topology_extensions: 22, set_bit(&mut leaf_80000001.result.ecx, 22, true); Ok(()) } @@ -220,6 +218,7 @@ impl super::AmdCpuid { .get_mut(&CpuidKey::leaf(0x80000008)) .ok_or(FeatureEntryError::MissingLeaf0x80000008)?; + // CPUID Fn8000_0008_ECX[15:12] (Field Name: ApicIdSize) // APIC ID size. The number of bits in the initial APIC20[ApicId] value that indicate // logical processor ID within a package. The size of this field determines the // maximum number of logical processors (MNLP) that the package could @@ -228,15 +227,11 @@ impl super::AmdCpuid { // Fn8000_0008_ECX[NC]. A value of zero indicates that legacy methods must be // used to determine the maximum number of logical processors, as indicated by // CPUID Fn8000_0008_ECX[NC]. - // - // apic_id_size: 12..16, set_range(&mut leaf_80000008.result.ecx, 12..16, THREAD_ID_MAX_SIZE).unwrap(); + // CPUID Fn8000_0008_ECX[7:0] (Field Name: NC) // Number of physical threads - 1. The number of threads in the processor is NT+1 // (e.g., if NT = 0, then there is one thread). See “Legacy Method” on page 633. - // - // nt: 0..8, - // let sub = cpu_count .checked_sub(1) .ok_or(FeatureEntryError::NumberOfPhysicalThreadsOverflow)?; @@ -255,6 +250,7 @@ impl super::AmdCpuid { ) -> Result<(), ExtendedCacheTopologyError> { for i in 0.. { if let Some(subleaf) = self.get_mut(&CpuidKey::subleaf(0x8000001d, i)) { + // CPUID Fn8000_001D_EAX_x[7:5] (Field Name: CacheLevel) // Cache level. Identifies the level of this cache. Note that the enumeration value // is not necessarily equal to the cache level. // ```text @@ -265,10 +261,9 @@ impl super::AmdCpuid { // 011b Level 3 // 111b-100b Reserved. // ``` - // - // cache_level: 5..8 let cache_level = get_range(subleaf.result.eax, 5..8); + // CPUID Fn8000_001D_EAX_x[25:14] (Field Name: NumSharingCache) // Specifies the number of logical processors sharing the cache enumerated by N, // the value passed to the instruction in ECX. The number of logical processors // sharing this cache is the value of this field incremented by 1. To determine @@ -279,8 +274,6 @@ impl super::AmdCpuid { // // Logical processors with the same ShareId then share a cache. If // NumSharingCache+1 is not a power of two, round it up to the next power of two. - // - // num_sharing_cache: 14..26, match cache_level { // L1 & L2 Cache @@ -334,16 +327,18 @@ impl super::AmdCpuid { .get_mut(&CpuidKey::leaf(0x8000001e)) .ok_or(ExtendedApicIdError::MissingLeaf0x8000001e)?; + // CPUID Fn8000_001E_EAX[31:0] (Field Name: ExtendedApicId) // Extended APIC ID. If MSR0000_001B[ApicEn] = 0, this field is reserved. - // - // extended_apic_id: 0..32, set_range(&mut leaf_8000001e.result.eax, 0..32, u32::from(cpu_index)) .map_err(ExtendedApicIdError::ExtendedApicId)?; - // compute_unit_id: 0..8, + // CPUID Fn8000_001E_EBX[7:0] (Field Name: ComputeUnitId) + // Compute unit ID. Identifies a Compute Unit, which may be one or more physical cores that + // each implement one or more logical processors. set_range(&mut leaf_8000001e.result.ebx, 0..8, core_id) .map_err(ExtendedApicIdError::ComputeUnitId)?; + // CPUID Fn8000_001E_EBX[15:8] (Field Name: ThreadsPerComputeUnit) // Threads per compute unit (zero-based count). The actual number of threads // per compute unit is the value of this field + 1. To determine which logical // processors (threads) belong to a given Compute Unit, determine a ShareId @@ -355,28 +350,24 @@ impl super::AmdCpuid { // Unit. (If ThreadsPerComputeUnit+1 is not a power of two, round it up to the // next power of two). // - // threads_per_compute_unit: 8..16, - // // SAFETY: We know `cpus_per_core > 0` therefore this is always safe. let sub = u32::from(cpus_per_core.checked_sub(1).unwrap()); set_range(&mut leaf_8000001e.result.ebx, 8..16, sub) .map_err(ExtendedApicIdError::ThreadPerComputeUnit)?; + // CPUID Fn8000_001E_ECX[10:8] (Field Name: NodesPerProcessor) // Specifies the number of nodes in the package/socket in which this logical // processor resides. Node in this context corresponds to a processor die. // Encoding is N-1, where N is the number of nodes present in the socket. // - // nodes_per_processor: 8..11, - // // SAFETY: We know the value always fits within the range and thus is always safe. // Set nodes per processor. set_range(&mut leaf_8000001e.result.ecx, 8..11, NODES_PER_PROCESSOR).unwrap(); + // CPUID Fn8000_001E_ECX[7:0] (Field Name: NodeId) // Specifies the ID of the node containing the current logical processor. NodeId // values are unique across the system. // - // node_id: 0..8, - // // Put all the cpus in the same node. set_range(&mut leaf_8000001e.result.ecx, 0..8, 0).unwrap(); From b2136d2e20967f23f42edad3c77ddcfe70fbbea9 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 10:59:57 +0000 Subject: [PATCH 360/464] refactor(vmm): Remove unneeded constants There is no benefit defining constants that are used only once. Rather it makes harder to read code since the definition and usage are far apart. Signed-off-by: Takahiro Itazuri --- .../src/cpu_config/x86_64/cpuid/normalize.rs | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index 18963875813..da339e4f7a5 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -221,26 +221,13 @@ impl super::Cpuid { cpu_index: u8, cpu_count: u8, ) -> Result<(), FeatureInformationError> { - // Flush a cache line size. - const EBX_CLFLUSH_CACHELINE: u32 = 8; - - // PDCM: Perfmon and Debug Capability. - const ECX_PDCM_BITINDEX: u8 = 15; - - // TSC-Deadline. - const ECX_TSC_DEADLINE_BITINDEX: u8 = 24; - - // CPU is running on a hypervisor. - const ECX_HYPERVISOR_BITINDEX: u8 = 31; - let leaf_1 = self .get_mut(&CpuidKey::leaf(0x1)) .ok_or(FeatureInformationError::MissingLeaf1)?; // CPUID.01H:EBX[15:08] // CLFLUSH line size (Value * 8 = cache line size in bytes; used also by CLFLUSHOPT). - set_range(&mut leaf_1.result.ebx, 8..16, EBX_CLFLUSH_CACHELINE) - .map_err(FeatureInformationError::Clflush)?; + set_range(&mut leaf_1.result.ebx, 8..16, 8).map_err(FeatureInformationError::Clflush)?; // CPUID.01H:EBX[23:16] // Maximum number of addressable IDs for logical processors in this physical package. @@ -266,15 +253,15 @@ impl super::Cpuid { // CPUID.01H:ECX[15] (Mnemonic: PDCM) // Performance and Debug Capability: A value of 1 indicates the processor supports the // performance and debug feature indication MSR IA32_PERF_CAPABILITIES. - set_bit(&mut leaf_1.result.ecx, ECX_PDCM_BITINDEX, false); + set_bit(&mut leaf_1.result.ecx, 15, false); // CPUID.01H:ECX[24] (Mnemonic: TSC-Deadline) // A value of 1 indicates that the processor’s local APIC timer supports one-shot operation // using a TSC deadline value. - set_bit(&mut leaf_1.result.ecx, ECX_TSC_DEADLINE_BITINDEX, true); + set_bit(&mut leaf_1.result.ecx, 24, true); // CPUID.01H:ECX[31] (Mnemonic: Hypervisor) - set_bit(&mut leaf_1.result.ecx, ECX_HYPERVISOR_BITINDEX, true); + set_bit(&mut leaf_1.result.ecx, 31, true); // CPUID.01H:EDX[28] (Mnemonic: HTT) // Max APIC IDs reserved field is Valid. A value of 0 for HTT indicates there is only a From ebbf837be223182bcb98c5c81d988e0ad7828c97 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 11:24:37 +0000 Subject: [PATCH 361/464] refactor(vmm): Refer to Intel SDM rather than Intel x2APIC spec As mentioned in [1], Intel 64 Architecture x2APIC Specification has been merged into Volumes 2 and 3 of Intel 64 and IA-32 architectures software developer's manual. [1]: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html Signed-off-by: Takahiro Itazuri --- .../src/cpu_config/x86_64/cpuid/normalize.rs | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index da339e4f7a5..31fc3415d24 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -317,47 +317,37 @@ impl super::Cpuid { subleaf.result.edx = u32::from(cpu_index); subleaf.flags = KvmCpuidFlags::SIGNIFICANT_INDEX; - // "If SMT is not present in a processor implementation but CPUID leaf 0BH is - // supported, CPUID.EAX=0BH, ECX=0 will return EAX = 0, EBX = 1 and - // level type = 1. Number of logical processors at the core level is - // reported at level type = 2." (Intel® 64 Architecture x2APIC - // Specification, Ch. 2.8) match index { // CPUID.(EAX=0BH,ECX=N):EAX[4:0] - // Number of bits to shift right on x2APIC ID to get a unique topology ID of the - // next level type*. All logical processors with the same - // next level ID share current level. - // - // *Software should use this field (EAX[4:0]) to enumerate processor topology of - // the system. + // The number of bits that the x2APIC ID must be shifted to the right to address + // instances of the next higher-scoped domain. When logical processor is not + // supported by the processor, the value of this field at the Logical Processor + // domain sub-leaf may be returned as either 0 (no allocated bits in the x2APIC + // ID) or 1 (one allocated bit in the x2APIC ID); software should plan + // accordingly. // CPUID.(EAX=0BH,ECX=N):EBX[15:0] - // Number of logical processors at this level type. The number reflects - // configuration as shipped by Intel**. - // - // **Software must not use EBX[15:0] to enumerate processor topology of the - // system. This value in this field (EBX[15:0]) is only - // intended for display/diagnostic purposes. The actual - // number of logical processors available to BIOS/OS/Applications may be - // different from the value of EBX[15:0], depending on - // software and platform hardware configurations. + // The number of logical processors across all instances of this domain within + // the next-higher scoped domain. (For example, in a processor socket/package + // comprising "M" dies of "N" cores each, where each core has "L" logical + // processors, the "die" domain sub-leaf value of this field would be M*N*L.) + // This number reflects configuration as shipped by Intel. Note, software must + // not use this field to enumerate processor topology. // CPUID.(EAX=0BH,ECX=N):ECX[7:0] - // Level number. Same value in ECX input. + // The input ECX sub-leaf index. // CPUID.(EAX=0BH,ECX=N):ECX[15:8] - // Level type*** + // Domain Type. This field provides an identification value which indicates the + // domain as shown below. Although domains are ordered, their assigned + // identification values are not and software should not depend on it. // - // If an input value n in ECX returns the invalid level-type of 0 in ECX[15:8], - // other input values with ECX>n also return 0 in ECX[15:8]. + // Hierarchy Domain Domain Type Identification Value + // ----------------------------------------------------------------- + // Lowest Logical Processor 1 + // Highest Core 2 // - // ***The value of the “level type” field is not related to level numbers in any - // way, higher “level type” values do not mean higher - // levels. Level type field has the following encoding: - // - 0: Invalid. - // - 1: SMT. - // - 2: Core. - // - 3-255: Reserved. + // (Note that enumeration values of 0 and 3-255 are reserved.) // Thread Level Topology; index = 0 0 => { From 4a9ccd29c023ce2a83f497c185b3a4e66c863ed6 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 11:48:40 +0000 Subject: [PATCH 362/464] refactor(vmm): Update variable names and comments with SDM notation The last commit updates quotes of Intel specification from x2APIC spec to Intel SDM. In accrodance with the change, update variable names and comments (e.g. level => domain) and correct some comments appropriately. Signed-off-by: Takahiro Itazuri --- .../src/cpu_config/x86_64/cpuid/normalize.rs | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index 31fc3415d24..a867981ebfe 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -64,10 +64,10 @@ pub enum ExtendedTopologyError { ApicId(CheckedAssignError), /// Failed to set `Number of logical processors at this level type`: {0} LogicalProcessors(CheckedAssignError), - /// Failed to set `Level Type`: {0} - LevelType(CheckedAssignError), - /// Failed to set `Level Number`: {0} - LevelNumber(CheckedAssignError), + /// Failed to set `Domain Type`: {0} + DomainType(CheckedAssignError), + /// Failed to set `Input ECX`: {0} + InputEcx(CheckedAssignError), /// Failed to set all leaves, as more than `u32::MAX` sub-leaves are present: {0} Overflow(>::Error), } @@ -282,10 +282,6 @@ impl super::Cpuid { cpu_bits: u8, cpus_per_core: u8, ) -> Result<(), ExtendedTopologyError> { - /// Level type used for setting thread level processor topology. - const LEVEL_TYPE_THREAD: u32 = 1; - /// Level type used for setting core level processor topology. - const LEVEL_TYPE_CORE: u32 = 2; /// The APIC ID shift in leaf 0xBh specifies the number of bits to shit the x2APIC ID to /// get a unique topology of the next level. This allows 128 logical /// processors/package. @@ -308,7 +304,7 @@ impl super::Cpuid { for index in 0.. { if let Some(subleaf) = self.get_mut(&CpuidKey::subleaf(0xB, index)) { - // reset eax, ebx, ecx + // Reset eax, ebx, ecx subleaf.result.eax = 0; subleaf.result.ebx = 0; subleaf.result.ecx = 0; @@ -349,47 +345,45 @@ impl super::Cpuid { // // (Note that enumeration values of 0 and 3-255 are reserved.) - // Thread Level Topology; index = 0 + // Logical processor domain 0 => { // To get the next level APIC ID, shift right with at most 1 because we have - // maximum 2 hyperthreads per core that can be represented by 1 bit. + // maximum 2 logical procerssors per core that can be represented by 1 bit. set_range(&mut subleaf.result.eax, 0..5, u32::from(cpu_bits)) .map_err(ExtendedTopologyError::ApicId)?; // When cpu_count == 1 or HT is disabled, there is 1 logical core at this - // level Otherwise there are 2 + // domain; otherwise there are 2 set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpus_per_core)) .map_err(ExtendedTopologyError::LogicalProcessors)?; - set_range(&mut subleaf.result.ecx, 8..16, LEVEL_TYPE_THREAD) - .map_err(ExtendedTopologyError::LevelType)?; + // Skip setting 0 to ECX[7:0] since it's already reset to 0. + + // Set the domain type identification value for logical processor, + set_range(&mut subleaf.result.ecx, 8..16, 1) + .map_err(ExtendedTopologyError::DomainType)?; } - // Core Level Processor Topology; index = 1 + // Core domain 1 => { set_range(&mut subleaf.result.eax, 0..5, LEAFBH_INDEX1_APICID) .map_err(ExtendedTopologyError::ApicId)?; + // Configure such that the next higher-scoped domain (i.e. socket) include + // all logical processors. set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpu_count)) .map_err(ExtendedTopologyError::LogicalProcessors)?; - // We expect here as this is an extremely rare case that is unlikely to ever - // occur. It would require manual editing of the CPUID structure to push - // more than 2^32 subleaves. - let sub = index; - set_range(&mut subleaf.result.ecx, 0..8, sub) - .map_err(ExtendedTopologyError::LevelNumber)?; - - set_range(&mut subleaf.result.ecx, 8..16, LEVEL_TYPE_CORE) - .map_err(ExtendedTopologyError::LevelType)?; + // Setting the input ECX value (i.e. `index`) + set_range(&mut subleaf.result.ecx, 0..8, index) + .map_err(ExtendedTopologyError::InputEcx)?; + + // Set the domain type identification value for core. + set_range(&mut subleaf.result.ecx, 8..16, 2) + .map_err(ExtendedTopologyError::DomainType)?; } - // Core Level Processor Topology; index >=2 - // No other levels available; This should already be set correctly, - // and it is added here as a "re-enforcement" in case we run on - // different hardware _ => { // We expect here as this is an extremely rare case that is unlikely to ever - // occur. It would require manual editing of the CPUID structure to push - // more than 2^32 subleaves. + // occur. subleaf.result.ecx = index; } } From 68e7a4c75018bc8ef9d50de66553500b6aa9f28e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 18:14:07 +0000 Subject: [PATCH 363/464] refactor(vmm): Error if subleaf >= 2 given for leaf 0xB Our supported kernels no longer return any subleaves >= 1. We inserted subleaf 1 intentionally but subleaves >= 2 are not expected there. Signed-off-by: Takahiro Itazuri --- src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index a867981ebfe..cddfc2b53b2 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -70,6 +70,8 @@ pub enum ExtendedTopologyError { InputEcx(CheckedAssignError), /// Failed to set all leaves, as more than `u32::MAX` sub-leaves are present: {0} Overflow(>::Error), + /// Unexpected subleaf: {0} + UnexpectedSubleaf(u32) } /// Error type for setting leaf 0x80000006 of Cpuid::normalize(). @@ -382,9 +384,11 @@ impl super::Cpuid { .map_err(ExtendedTopologyError::DomainType)?; } _ => { - // We expect here as this is an extremely rare case that is unlikely to ever - // occur. - subleaf.result.ecx = index; + // KVM no longer returns any subleaf numbers greater than 0. The patch was + // merged in v6.2 and backported to v5.10. Subleaves >= 2 should not be + // included. + // https://github.com/torvalds/linux/commit/45e966fcca03ecdcccac7cb236e16eea38cc18af + return Err(ExtendedTopologyError::UnexpectedSubleaf(index)); } } } else { From 6220711825e19859234baf2a288d0a518d142f2c Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 12:24:13 +0000 Subject: [PATCH 364/464] fix(vmm): Calc right-shift bits to address socket ID The number of bits that the x2APIC ID must be shifted to the right to address instances of the socket domain, which is next higher-scoped domain to the core domain, was hardcoded as 7. That means up to 128 vcpus support. Currently the max vcpu count is hardcoded as 32, so it is enough but we might want to increase it in the future. To avoid unexpected issues when increasing the max vcpu count, calculate the value based on the max vCPU count. Signed-off-by: Takahiro Itazuri --- .../src/cpu_config/x86_64/cpuid/normalize.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index cddfc2b53b2..bdf0e1c01ae 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -4,6 +4,7 @@ use crate::cpu_config::x86_64::cpuid::{ CpuidEntry, CpuidKey, CpuidRegisters, CpuidTrait, KvmCpuidFlags, cpuid, }; +use crate::vmm_config::machine_config::MAX_SUPPORTED_VCPUS; /// Error type for [`super::Cpuid::normalize`]. #[allow(clippy::module_name_repetitions)] @@ -284,11 +285,6 @@ impl super::Cpuid { cpu_bits: u8, cpus_per_core: u8, ) -> Result<(), ExtendedTopologyError> { - /// The APIC ID shift in leaf 0xBh specifies the number of bits to shit the x2APIC ID to - /// get a unique topology of the next level. This allows 128 logical - /// processors/package. - const LEAFBH_INDEX1_APICID: u32 = 7; - // The following commit changed the behavior of KVM_GET_SUPPORTED_CPUID to no longer // include CPUID.(EAX=0BH,ECX=1). // https://lore.kernel.org/all/20221027092036.2698180-1-pbonzini@redhat.com/ @@ -367,11 +363,17 @@ impl super::Cpuid { } // Core domain 1 => { - set_range(&mut subleaf.result.eax, 0..5, LEAFBH_INDEX1_APICID) - .map_err(ExtendedTopologyError::ApicId)?; - // Configure such that the next higher-scoped domain (i.e. socket) include // all logical processors. + // + // The CPUID.(EAX=0BH,ECX=1).EAX[4:0] value must be an integer N such that + // 2^N is greater than or equal to the maximum number of vCPUs. + set_range( + &mut subleaf.result.eax, + 0..5, + MAX_SUPPORTED_VCPUS.next_power_of_two().ilog2(), + ) + .map_err(ExtendedTopologyError::ApicId)?; set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpu_count)) .map_err(ExtendedTopologyError::LogicalProcessors)?; From f915b2341ccb6b998f9585d478c236ad35196120 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 18:27:13 +0000 Subject: [PATCH 365/464] refactor(vmm): Better error messages for CPUID normalization Show which combination of subleaf, register and bit(s) failed to set, remove unused error variant and reorder error variants in alphabetical order. Signed-off-by: Takahiro Itazuri --- .../cpu_config/x86_64/cpuid/amd/normalize.rs | 32 ++++++++++--------- .../x86_64/cpuid/intel/normalize.rs | 14 ++++---- .../src/cpu_config/x86_64/cpuid/normalize.rs | 32 +++++++++---------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs index f0ee9322e12..52bb806472d 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs @@ -48,10 +48,10 @@ pub enum PassthroughCacheTopologyError { pub enum FeatureEntryError { /// Missing leaf 0x80000008. MissingLeaf0x80000008, - /// Failed to set `nt` (number of physical threads) due to overflow. - NumberOfPhysicalThreadsOverflow, - /// Failed to set `nt` (number of physical threads). + /// Failed to set number of physical threads (CPUID.80000008H:ECX[7:0]): {0} NumberOfPhysicalThreads(CheckedAssignError), + /// Failed to set number of physical threads (CPUID.80000008H:ECX[7:0]) due to overflow. + NumberOfPhysicalThreadsOverflow, } /// Error type for setting leaf 0x8000001d section of [`super::AmdCpuid::normalize`]. @@ -59,22 +59,24 @@ pub enum FeatureEntryError { pub enum ExtendedCacheTopologyError { /// Missing leaf 0x8000001d. MissingLeaf0x8000001d, - /// Failed to set `num_sharing_cache` due to overflow. - NumSharingCacheOverflow, - /// Failed to set `num_sharing_cache`: {0} - NumSharingCache(CheckedAssignError), + #[rustfmt::skip] + /// Failed to set number of logical processors sharing cache(CPUID.(EAX=8000001DH,ECX={0}):EAX[25:14]): {1} + NumSharingCache(u32, CheckedAssignError), + #[rustfmt::skip] + /// Failed to set number of logical processors sharing cache (CPUID.(EAX=8000001DH,ECX={0}):EAX[25:14]) due to overflow. + NumSharingCacheOverflow(u32), } /// Error type for setting leaf 0x8000001e section of [`super::AmdCpuid::normalize`]. #[derive(Debug, thiserror::Error, displaydoc::Display, Eq, PartialEq)] pub enum ExtendedApicIdError { + /// Failed to set compute unit ID (CPUID.8000001EH:EBX[7:0]): {0} + ComputeUnitId(CheckedAssignError), + /// Failed to set extended APIC ID (CPUID.8000001EH:EAX[31:0]): {0} + ExtendedApicId(CheckedAssignError), /// Missing leaf 0x8000001e. MissingLeaf0x8000001e, - /// Failed to set `extended_apic_id`: {0} - ExtendedApicId(CheckedAssignError), - /// Failed to set `compute_unit_id`: {0} - ComputeUnitId(CheckedAssignError), - /// Failed to set `threads_per_compute_unit`: {0} + /// Failed to set threads per core unit (CPUID:8000001EH:EBX[15:8]): {0} ThreadPerComputeUnit(CheckedAssignError), } @@ -282,16 +284,16 @@ impl super::AmdCpuid { // SAFETY: We know `cpus_per_core > 0` therefore this is always safe. let sub = u32::from(cpus_per_core.checked_sub(1).unwrap()); set_range(&mut subleaf.result.eax, 14..26, sub) - .map_err(ExtendedCacheTopologyError::NumSharingCache)?; + .map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?; } // L3 Cache // The L3 cache is shared among all the logical threads 3 => { let sub = cpu_count .checked_sub(1) - .ok_or(ExtendedCacheTopologyError::NumSharingCacheOverflow)?; + .ok_or(ExtendedCacheTopologyError::NumSharingCacheOverflow(i))?; set_range(&mut subleaf.result.eax, 14..26, u32::from(sub)) - .map_err(ExtendedCacheTopologyError::NumSharingCache)?; + .map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?; } _ => (), } diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 0bfc5d89632..af4058298da 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -34,14 +34,14 @@ pub enum NormalizeCpuidError { #[allow(clippy::enum_variant_names)] #[derive(Debug, thiserror::Error, displaydoc::Display, Eq, PartialEq)] pub enum DeterministicCacheError { - /// Failed to set `Maximum number of addressable IDs for logical processors sharing this cache` due to underflow in cpu count. - MaxCpusPerCoreUnderflow, - /// Failed to set `Maximum number of addressable IDs for logical processors sharing this cache`: {0}. - MaxCpusPerCore(CheckedAssignError), - /// Failed to set `Maximum number of addressable IDs for processor cores in the physical package` due to underflow in cores. - MaxCorePerPackageUnderflow, - /// Failed to set `Maximum number of addressable IDs for processor cores in the physical package`: {0}. + /// Failed to set max addressable core ID in physical package (CPUID.04H:EAX[31:26]): {0}. MaxCorePerPackage(CheckedAssignError), + /// Failed to set max addressable core ID in physical package (CPUID.04H:EAX[31:26]) due to underflow in cores. + MaxCorePerPackageUnderflow, + /// Failed to set max addressable processor ID sharing cache (CPUID.04H:EAX[25:14]): {0}. + MaxCpusPerCore(CheckedAssignError), + /// Failed to set max addressable processor ID sharing cache (CPUID.04H:EAX[25:14]) due to underflow in cpu count. + MaxCpusPerCoreUnderflow, } /// We always use this brand string. diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index bdf0e1c01ae..73c4a3c793e 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -61,16 +61,14 @@ pub enum GetMaxCpusPerPackageError { #[rustfmt::skip] #[derive(Debug, thiserror::Error, displaydoc::Display, Eq, PartialEq)] pub enum ExtendedTopologyError { - /// Failed to set `Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type`: {0} - ApicId(CheckedAssignError), - /// Failed to set `Number of logical processors at this level type`: {0} - LogicalProcessors(CheckedAssignError), - /// Failed to set `Domain Type`: {0} - DomainType(CheckedAssignError), - /// Failed to set `Input ECX`: {0} - InputEcx(CheckedAssignError), - /// Failed to set all leaves, as more than `u32::MAX` sub-leaves are present: {0} - Overflow(>::Error), + /// Failed to set domain type (CPUID.(EAX=0xB,ECX={0}):ECX[15:8]): {1} + DomainType(u32, CheckedAssignError), + /// Failed to set input ECX (CPUID.(EAX=0xB,ECX={0}):ECX[7:0]): {1} + InputEcx(u32, CheckedAssignError), + /// Failed to set number of logical processors (CPUID.(EAX=0xB,ECX={0}):EBX[15:0]): {1} + NumLogicalProcs(u32, CheckedAssignError), + /// Failed to set right-shift bits (CPUID.(EAX=0xB,ECX={0}):EAX[4:0]): {1} + RightShiftBits(u32, CheckedAssignError), /// Unexpected subleaf: {0} UnexpectedSubleaf(u32) } @@ -348,18 +346,18 @@ impl super::Cpuid { // To get the next level APIC ID, shift right with at most 1 because we have // maximum 2 logical procerssors per core that can be represented by 1 bit. set_range(&mut subleaf.result.eax, 0..5, u32::from(cpu_bits)) - .map_err(ExtendedTopologyError::ApicId)?; + .map_err(|err| ExtendedTopologyError::RightShiftBits(index, err))?; // When cpu_count == 1 or HT is disabled, there is 1 logical core at this // domain; otherwise there are 2 set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpus_per_core)) - .map_err(ExtendedTopologyError::LogicalProcessors)?; + .map_err(|err| ExtendedTopologyError::NumLogicalProcs(index, err))?; // Skip setting 0 to ECX[7:0] since it's already reset to 0. // Set the domain type identification value for logical processor, set_range(&mut subleaf.result.ecx, 8..16, 1) - .map_err(ExtendedTopologyError::DomainType)?; + .map_err(|err| ExtendedTopologyError::DomainType(index, err))?; } // Core domain 1 => { @@ -373,17 +371,17 @@ impl super::Cpuid { 0..5, MAX_SUPPORTED_VCPUS.next_power_of_two().ilog2(), ) - .map_err(ExtendedTopologyError::ApicId)?; + .map_err(|err| ExtendedTopologyError::RightShiftBits(index, err))?; set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpu_count)) - .map_err(ExtendedTopologyError::LogicalProcessors)?; + .map_err(|err| ExtendedTopologyError::NumLogicalProcs(index, err))?; // Setting the input ECX value (i.e. `index`) set_range(&mut subleaf.result.ecx, 0..8, index) - .map_err(ExtendedTopologyError::InputEcx)?; + .map_err(|err| ExtendedTopologyError::InputEcx(index, err))?; // Set the domain type identification value for core. set_range(&mut subleaf.result.ecx, 8..16, 2) - .map_err(ExtendedTopologyError::DomainType)?; + .map_err(|err| ExtendedTopologyError::DomainType(index, err))?; } _ => { // KVM no longer returns any subleaf numbers greater than 0. The patch was From 95fc34b18deb4330e5088f0afee98abd1425e935 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 19:50:29 +0000 Subject: [PATCH 366/464] refactor(vmm): Bit-range manipulation with RangeInclusive Since CPUID notation uses the upper bound inclusive, use RangeInclusive instead of Range. Also, make set_range() and get_range() more readable and reliable by always validating that `y` fits within the given range and by asserting `end` is less than 32. Signed-off-by: Takahiro Itazuri --- .../cpu_config/x86_64/cpuid/amd/normalize.rs | 20 ++-- .../x86_64/cpuid/intel/normalize.rs | 8 +- .../src/cpu_config/x86_64/cpuid/normalize.rs | 106 ++++++++---------- 3 files changed, 61 insertions(+), 73 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs index 52bb806472d..e481bc17681 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs @@ -229,7 +229,7 @@ impl super::AmdCpuid { // Fn8000_0008_ECX[NC]. A value of zero indicates that legacy methods must be // used to determine the maximum number of logical processors, as indicated by // CPUID Fn8000_0008_ECX[NC]. - set_range(&mut leaf_80000008.result.ecx, 12..16, THREAD_ID_MAX_SIZE).unwrap(); + set_range(&mut leaf_80000008.result.ecx, 12..=15, THREAD_ID_MAX_SIZE).unwrap(); // CPUID Fn8000_0008_ECX[7:0] (Field Name: NC) // Number of physical threads - 1. The number of threads in the processor is NT+1 @@ -237,7 +237,7 @@ impl super::AmdCpuid { let sub = cpu_count .checked_sub(1) .ok_or(FeatureEntryError::NumberOfPhysicalThreadsOverflow)?; - set_range(&mut leaf_80000008.result.ecx, 0..8, u32::from(sub)) + set_range(&mut leaf_80000008.result.ecx, 0..=7, u32::from(sub)) .map_err(FeatureEntryError::NumberOfPhysicalThreads)?; Ok(()) @@ -263,7 +263,7 @@ impl super::AmdCpuid { // 011b Level 3 // 111b-100b Reserved. // ``` - let cache_level = get_range(subleaf.result.eax, 5..8); + let cache_level = get_range(subleaf.result.eax, 5..=7); // CPUID Fn8000_001D_EAX_x[25:14] (Field Name: NumSharingCache) // Specifies the number of logical processors sharing the cache enumerated by N, @@ -283,7 +283,7 @@ impl super::AmdCpuid { 1 | 2 => { // SAFETY: We know `cpus_per_core > 0` therefore this is always safe. let sub = u32::from(cpus_per_core.checked_sub(1).unwrap()); - set_range(&mut subleaf.result.eax, 14..26, sub) + set_range(&mut subleaf.result.eax, 14..=25, sub) .map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?; } // L3 Cache @@ -292,7 +292,7 @@ impl super::AmdCpuid { let sub = cpu_count .checked_sub(1) .ok_or(ExtendedCacheTopologyError::NumSharingCacheOverflow(i))?; - set_range(&mut subleaf.result.eax, 14..26, u32::from(sub)) + set_range(&mut subleaf.result.eax, 14..=25, u32::from(sub)) .map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?; } _ => (), @@ -331,13 +331,13 @@ impl super::AmdCpuid { // CPUID Fn8000_001E_EAX[31:0] (Field Name: ExtendedApicId) // Extended APIC ID. If MSR0000_001B[ApicEn] = 0, this field is reserved. - set_range(&mut leaf_8000001e.result.eax, 0..32, u32::from(cpu_index)) + set_range(&mut leaf_8000001e.result.eax, 0..=31, u32::from(cpu_index)) .map_err(ExtendedApicIdError::ExtendedApicId)?; // CPUID Fn8000_001E_EBX[7:0] (Field Name: ComputeUnitId) // Compute unit ID. Identifies a Compute Unit, which may be one or more physical cores that // each implement one or more logical processors. - set_range(&mut leaf_8000001e.result.ebx, 0..8, core_id) + set_range(&mut leaf_8000001e.result.ebx, 0..=7, core_id) .map_err(ExtendedApicIdError::ComputeUnitId)?; // CPUID Fn8000_001E_EBX[15:8] (Field Name: ThreadsPerComputeUnit) @@ -354,7 +354,7 @@ impl super::AmdCpuid { // // SAFETY: We know `cpus_per_core > 0` therefore this is always safe. let sub = u32::from(cpus_per_core.checked_sub(1).unwrap()); - set_range(&mut leaf_8000001e.result.ebx, 8..16, sub) + set_range(&mut leaf_8000001e.result.ebx, 8..=15, sub) .map_err(ExtendedApicIdError::ThreadPerComputeUnit)?; // CPUID Fn8000_001E_ECX[10:8] (Field Name: NodesPerProcessor) @@ -364,14 +364,14 @@ impl super::AmdCpuid { // // SAFETY: We know the value always fits within the range and thus is always safe. // Set nodes per processor. - set_range(&mut leaf_8000001e.result.ecx, 8..11, NODES_PER_PROCESSOR).unwrap(); + set_range(&mut leaf_8000001e.result.ecx, 8..=10, NODES_PER_PROCESSOR).unwrap(); // CPUID Fn8000_001E_ECX[7:0] (Field Name: NodeId) // Specifies the ID of the node containing the current logical processor. NodeId // values are unique across the system. // // Put all the cpus in the same node. - set_range(&mut leaf_8000001e.result.ecx, 0..8, 0).unwrap(); + set_range(&mut leaf_8000001e.result.ecx, 0..=7, 0).unwrap(); Ok(()) } diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index af4058298da..923fc67543e 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -99,7 +99,7 @@ impl super::IntelCpuid { // CPUID.04H:EAX[7:5] // Cache Level (Starts at 1) - let cache_level = get_range(subleaf.result.eax, 5..8); + let cache_level = get_range(subleaf.result.eax, 5..=7); // CPUID.04H:EAX[25:14] // Maximum number of addressable IDs for logical processors sharing this cache. @@ -116,7 +116,7 @@ impl super::IntelCpuid { // The L1 & L2 cache is shared by at most 2 hyperthreads 1 | 2 => { let sub = u32::from(cpus_per_core.checked_sub(1).unwrap()); - set_range(&mut subleaf.result.eax, 14..26, sub) + set_range(&mut subleaf.result.eax, 14..=25, sub) .map_err(DeterministicCacheError::MaxCpusPerCore)?; } // L3 Cache @@ -127,7 +127,7 @@ impl super::IntelCpuid { .checked_sub(1) .ok_or(DeterministicCacheError::MaxCpusPerCoreUnderflow)?, ); - set_range(&mut subleaf.result.eax, 14..26, sub) + set_range(&mut subleaf.result.eax, 14..=25, sub) .map_err(DeterministicCacheError::MaxCpusPerCore)?; } _ => (), @@ -150,7 +150,7 @@ impl super::IntelCpuid { let sub = u32::from(cores) .checked_sub(1) .ok_or(DeterministicCacheError::MaxCorePerPackageUnderflow)?; - set_range(&mut subleaf.result.eax, 26..32, sub) + set_range(&mut subleaf.result.eax, 26..=31, sub) .map_err(DeterministicCacheError::MaxCorePerPackage)?; } else { break; diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs index 73c4a3c793e..f9359036f5f 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/normalize.rs @@ -95,66 +95,54 @@ pub fn set_bit(x: &mut u32, bit: u8, y: bool) { } /// Sets a given range to a given value. -#[allow(clippy::arithmetic_side_effects)] pub fn set_range( x: &mut u32, - range: std::ops::Range, + range: std::ops::RangeInclusive, y: u32, ) -> Result<(), CheckedAssignError> { - debug_assert!(range.end >= range.start); - match range.end - range.start { - z @ 0..=31 => { - if y >= 2u32.pow(u32::from(z)) { - Err(CheckedAssignError) - } else { - let shift = y << range.start; - *x = shift | (*x & !mask(range)); - Ok(()) - } - } - 32 => { - let shift = y << range.start; - *x = shift | (*x & !mask(range)); - Ok(()) - } - 33.. => Err(CheckedAssignError), + let start = *range.start(); + let end = *range.end(); + + debug_assert!(end >= start); + debug_assert!(end < 32); + + // Ensure `y` fits within the number of bits in the specified range. + // Note that + // - 1 <= `num_bits` <= 32 from the above assertion + // - if `num_bits` equals to 32, `y` always fits within it since `y` is `u32`. + let num_bits = end - start + 1; + if num_bits < 32 && y >= (1u32 << num_bits) { + return Err(CheckedAssignError); } + + let mask = get_mask(range); + *x = (*x & !mask) | (y << start); + + Ok(()) } + /// Gets a given range within a given value. -#[allow(clippy::arithmetic_side_effects)] -pub fn get_range(x: u32, range: std::ops::Range) -> u32 { - debug_assert!(range.end >= range.start); - (x & mask(range.clone())) >> range.start +pub fn get_range(x: u32, range: std::ops::RangeInclusive) -> u32 { + let start = *range.start(); + let end = *range.end(); + + debug_assert!(end >= start); + debug_assert!(end < 32); + + let mask = get_mask(range); + (x & mask) >> start } /// Returns a mask where the given range is ones. -#[allow( - clippy::as_conversions, - clippy::arithmetic_side_effects, - clippy::cast_possible_truncation -)] -const fn mask(range: std::ops::Range) -> u32 { - /// Returns a value where in the binary representation all bits to the right of the x'th bit - /// from the left are 1. - #[allow(clippy::unreachable)] - const fn shift(x: u8) -> u32 { - if x == 0 { - 0 - } else if x < u32::BITS as u8 { - (1 << x) - 1 - } else if x == u32::BITS as u8 { - u32::MAX - } else { - unreachable!() - } +const fn get_mask(range: std::ops::RangeInclusive) -> u32 { + let num_bits = *range.end() - *range.start() + 1; + let shift = *range.start(); + + if num_bits == 32 { + u32::MAX + } else { + ((1u32 << num_bits) - 1) << shift } - - debug_assert!(range.end >= range.start); - debug_assert!(range.end <= u32::BITS as u8); - - let front = shift(range.start); - let back = shift(range.end); - !front & back } // We use this 2nd implementation so we can conveniently define functions only used within @@ -228,7 +216,7 @@ impl super::Cpuid { // CPUID.01H:EBX[15:08] // CLFLUSH line size (Value * 8 = cache line size in bytes; used also by CLFLUSHOPT). - set_range(&mut leaf_1.result.ebx, 8..16, 8).map_err(FeatureInformationError::Clflush)?; + set_range(&mut leaf_1.result.ebx, 8..=15, 8).map_err(FeatureInformationError::Clflush)?; // CPUID.01H:EBX[23:16] // Maximum number of addressable IDs for logical processors in this physical package. @@ -240,7 +228,7 @@ impl super::Cpuid { get_max_cpus_per_package(cpu_count) .map_err(FeatureInformationError::GetMaxCpusPerPackage)?, ); - set_range(&mut leaf_1.result.ebx, 16..24, max_cpus_per_package) + set_range(&mut leaf_1.result.ebx, 16..=23, max_cpus_per_package) .map_err(FeatureInformationError::SetMaxCpusPerPackage)?; // CPUID.01H:EBX[31:24] @@ -248,7 +236,7 @@ impl super::Cpuid { // // The 8-bit initial APIC ID in EBX[31:24] is replaced by the 32-bit x2APIC ID, available // in Leaf 0BH and Leaf 1FH. - set_range(&mut leaf_1.result.ebx, 24..32, u32::from(cpu_index)) + set_range(&mut leaf_1.result.ebx, 24..=31, u32::from(cpu_index)) .map_err(FeatureInformationError::InitialApicId)?; // CPUID.01H:ECX[15] (Mnemonic: PDCM) @@ -345,18 +333,18 @@ impl super::Cpuid { 0 => { // To get the next level APIC ID, shift right with at most 1 because we have // maximum 2 logical procerssors per core that can be represented by 1 bit. - set_range(&mut subleaf.result.eax, 0..5, u32::from(cpu_bits)) + set_range(&mut subleaf.result.eax, 0..=4, u32::from(cpu_bits)) .map_err(|err| ExtendedTopologyError::RightShiftBits(index, err))?; // When cpu_count == 1 or HT is disabled, there is 1 logical core at this // domain; otherwise there are 2 - set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpus_per_core)) + set_range(&mut subleaf.result.ebx, 0..=15, u32::from(cpus_per_core)) .map_err(|err| ExtendedTopologyError::NumLogicalProcs(index, err))?; // Skip setting 0 to ECX[7:0] since it's already reset to 0. // Set the domain type identification value for logical processor, - set_range(&mut subleaf.result.ecx, 8..16, 1) + set_range(&mut subleaf.result.ecx, 8..=15, 1) .map_err(|err| ExtendedTopologyError::DomainType(index, err))?; } // Core domain @@ -368,19 +356,19 @@ impl super::Cpuid { // 2^N is greater than or equal to the maximum number of vCPUs. set_range( &mut subleaf.result.eax, - 0..5, + 0..=4, MAX_SUPPORTED_VCPUS.next_power_of_two().ilog2(), ) .map_err(|err| ExtendedTopologyError::RightShiftBits(index, err))?; - set_range(&mut subleaf.result.ebx, 0..16, u32::from(cpu_count)) + set_range(&mut subleaf.result.ebx, 0..=15, u32::from(cpu_count)) .map_err(|err| ExtendedTopologyError::NumLogicalProcs(index, err))?; // Setting the input ECX value (i.e. `index`) - set_range(&mut subleaf.result.ecx, 0..8, index) + set_range(&mut subleaf.result.ecx, 0..=7, index) .map_err(|err| ExtendedTopologyError::InputEcx(index, err))?; // Set the domain type identification value for core. - set_range(&mut subleaf.result.ecx, 8..16, 2) + set_range(&mut subleaf.result.ecx, 8..=15, 2) .map_err(|err| ExtendedTopologyError::DomainType(index, err))?; } _ => { From 2ad05701ffa16b1df3b07b4a0b88a49d7200e19c Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 15:47:02 +0000 Subject: [PATCH 367/464] doc: Simplify normalized register list EAX, EBX, ECX and EDX are the all registers returned. Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpuid-normalization.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index 2eb743add22..b2d2238ae69 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -28,15 +28,15 @@ See also: [boot protocol settings](boot-protocol.md) ## Intel-specific CPUID normalization -| Description | Leaf | Subleaf | Register | Bits | -| -------------------------------------------------------------- | :--------------------------------: | :-----: | :----------------: | :---: | -| Update deterministic cache parameters | 0x4 | all | EAX | 31:14 | -| Disable Intel Turbo Boost technology | 0x6 | - | EAX | 1 | -| Disable frequency selection | 0x6 | - | ECX | 3 | -| Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 | -| Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 | -| Disable performance monitoring | 0xa | - | EAX, EBX, ECX, EDX | all | -| Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | EAX, EBX, ECX, EDX | all | +| Description | Leaf | Subleaf | Register | Bits | +| -------------------------------------------------------------- | :--------------------------------: | :-----: | :------: | :---: | +| Update deterministic cache parameters | 0x4 | all | EAX | 31:14 | +| Disable Intel Turbo Boost technology | 0x6 | - | EAX | 1 | +| Disable frequency selection | 0x6 | - | ECX | 3 | +| Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 | +| Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 | +| Disable performance monitoring | 0xa | - | all | all | +| Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | all | all | ## AMD-specifc CPUID normalization From 9ea85d52d17bbce2a68d16ceacb359ed43ede25f Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 13:51:21 +0000 Subject: [PATCH 368/464] feat(vmm): Normalize CPUID leaf 0x1F Intel Sapphire Rapids has CPUID leaf 0x1F that is a preferred superset to leaf 0xB. Intel recommends using leaf 0x1F when available rather than leaf 0xB. We don't use any other domains than ones supported leaf 0xB, so just copy leaf 0xB to leaf 0x1F. Signed-off-by: Takahiro Itazuri --- docs/cpu_templates/cpuid-normalization.md | 1 + .../x86_64/cpuid/intel/normalize.rs | 129 ++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index b2d2238ae69..6a15ff4a9e0 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -36,6 +36,7 @@ See also: [boot protocol settings](boot-protocol.md) | Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 | | Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 | | Disable performance monitoring | 0xa | - | all | all | +| Fill v2 extended topology enumeration leaf | 0x1f | all | all | all | | Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | all | all | ## AMD-specifc CPUID normalization diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 923fc67543e..110cd630e0b 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -73,6 +73,7 @@ impl super::IntelCpuid { self.update_power_management_entry()?; self.update_extended_feature_flags_entry()?; self.update_performance_monitoring_entry()?; + self.update_extended_topology_v2_entry(); self.update_brand_string_entry()?; Ok(()) @@ -210,6 +211,29 @@ impl super::IntelCpuid { Ok(()) } + /// Update extended topology v2 entry + /// + /// CPUID leaf 1FH is a preferred superset to leaf 0xB. Intel recommends using leaf 0x1F when + /// available rather than leaf 0xB. + /// + /// Since we don't use any domains than ones supported in leaf 0xB, we just copy contents of + /// leaf 0xB to leaf 0x1F. + fn update_extended_topology_v2_entry(&mut self) { + // Skip if leaf 0x1F does not exist. + if self.get(&CpuidKey::leaf(0x1F)).is_none() { + return; + } + + for index in 0.. { + if let Some(subleaf) = self.get(&CpuidKey::subleaf(0xB, index)) { + self.0 + .insert(CpuidKey::subleaf(0x1F, index), subleaf.clone()); + } else { + break; + } + } + } + fn update_brand_string_entry(&mut self) -> Result<(), NormalizeCpuidError> { // Get host brand string. let host_brand_string: [u8; BRAND_STRING_LENGTH] = host_brand_string(); @@ -331,9 +355,12 @@ mod tests { clippy::as_conversions )] + use std::collections::BTreeMap; use std::ffi::CStr; use super::*; + use crate::cpu_config::x86_64::cpuid::{CpuidEntry, IntelCpuid, KvmCpuidFlags}; + #[test] fn default_brand_string_test() { let brand_string = b"Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz\0\0"; @@ -394,4 +421,106 @@ mod tests { assert!((leaf_7_0.result.ebx & (1 << 6)) > 0); assert!((leaf_7_0.result.ebx & (1 << 13)) > 0); } + + #[test] + fn test_update_extended_topology_v2_entry_no_leaf_0x1f() { + let mut cpuid = IntelCpuid(BTreeMap::from([( + CpuidKey { + leaf: 0xB, + subleaf: 0, + }, + CpuidEntry { + flags: KvmCpuidFlags::SIGNIFICANT_INDEX, + ..Default::default() + }, + )])); + + cpuid.update_extended_topology_v2_entry(); + + assert!( + cpuid + .get(&CpuidKey { + leaf: 0x1F, + subleaf: 0, + }) + .is_none() + ); + } + + #[test] + fn test_update_extended_topology_v2_entry() { + let mut cpuid = IntelCpuid(BTreeMap::from([ + ( + CpuidKey { + leaf: 0xB, + subleaf: 0, + }, + CpuidEntry { + flags: KvmCpuidFlags::SIGNIFICANT_INDEX, + result: CpuidRegisters { + eax: 0x1, + ebx: 0x2, + ecx: 0x3, + edx: 0x4, + }, + }, + ), + ( + CpuidKey { + leaf: 0xB, + subleaf: 1, + }, + CpuidEntry { + flags: KvmCpuidFlags::SIGNIFICANT_INDEX, + result: CpuidRegisters { + eax: 0xa, + ebx: 0xb, + ecx: 0xc, + edx: 0xd, + }, + }, + ), + ( + CpuidKey { + leaf: 0x1F, + subleaf: 0, + }, + CpuidEntry { + flags: KvmCpuidFlags::SIGNIFICANT_INDEX, + result: CpuidRegisters { + eax: 0xFFFFFFFF, + ebx: 0xFFFFFFFF, + ecx: 0xFFFFFFFF, + edx: 0xFFFFFFFF, + }, + }, + ), + ])); + + cpuid.update_extended_topology_v2_entry(); + + // Check leaf 0x1F, subleaf 0 is updated. + let leaf_1f_0 = cpuid + .get(&CpuidKey { + leaf: 0x1F, + subleaf: 0, + }) + .unwrap(); + assert_eq!(leaf_1f_0.result.eax, 0x1); + assert_eq!(leaf_1f_0.result.ebx, 0x2); + assert_eq!(leaf_1f_0.result.ecx, 0x3); + assert_eq!(leaf_1f_0.result.edx, 0x4); + + // Check lefa 0x1F, subleaf 1 is inserted. + let leaf_1f_1 = cpuid + .get(&CpuidKey { + leaf: 0x1F, + subleaf: 1, + }) + .unwrap(); + assert_eq!(leaf_1f_1.result.eax, 0xa); + assert_eq!(leaf_1f_1.result.ebx, 0xb); + assert_eq!(leaf_1f_1.result.ecx, 0xc); + assert_eq!(leaf_1f_1.result.edx, 0xd); + } } From 384a1a40a2d8fb4f6e5a1437d0173a0eacf9d742 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 17:58:05 +0000 Subject: [PATCH 369/464] refactor: Remove unneeded turbo fish (::) in unit test Some structs are imported in the last commit. Let's remove turbo fish! Signed-off-by: Takahiro Itazuri --- .../x86_64/cpuid/intel/normalize.rs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 110cd630e0b..2e22134e882 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -398,22 +398,21 @@ mod tests { #[test] fn test_update_extended_feature_flags_entry() { - let mut cpuid = - crate::cpu_config::x86_64::cpuid::IntelCpuid(std::collections::BTreeMap::from([( - crate::cpu_config::x86_64::cpuid::CpuidKey { - leaf: 0x7, - subleaf: 0, - }, - crate::cpu_config::x86_64::cpuid::CpuidEntry { - flags: crate::cpu_config::x86_64::cpuid::KvmCpuidFlags::SIGNIFICANT_INDEX, - ..Default::default() - }, - )])); + let mut cpuid = IntelCpuid(BTreeMap::from([( + CpuidKey { + leaf: 0x7, + subleaf: 0, + }, + CpuidEntry { + flags: KvmCpuidFlags::SIGNIFICANT_INDEX, + ..Default::default() + }, + )])); cpuid.update_extended_feature_flags_entry().unwrap(); let leaf_7_0 = cpuid - .get(&crate::cpu_config::x86_64::cpuid::CpuidKey { + .get(&CpuidKey { leaf: 0x7, subleaf: 0, }) From 30e857b4441ac93eed9b1cdc75466b5608117918 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 15:21:47 +0000 Subject: [PATCH 370/464] test: Skip frequency check if host not report it Intel Sapphire Rapids does not report its frequency in the model name string on host ("Intel(R) Xeon(R) Platinum 8488C"). Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_x86_64.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 270e3fa12e2..0fb51e5bd37 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -150,6 +150,8 @@ def test_brand_string(uvm_plain_any): * For Intel CPUs, the guest brand string should be: Intel(R) Xeon(R) Processor @ {host frequency} + or + Intel(R) Xeon(R) Processor where {host frequency} is the frequency reported by the host CPUID (e.g. 4.01GHz) * For AMD CPUs, the guest brand string should be: @@ -184,7 +186,9 @@ def test_brand_string(uvm_plain_any): cif = open("/proc/cpuinfo", "r", encoding="utf-8") cpu_info = cif.read() mo = re.search("model name.*:.* ([0-9]*.[0-9]*[G|M|T]Hz)", cpu_info) - assert mo + # Skip if host frequency is not reported + if mo is None: + return host_frequency = mo.group(1) # Assert the model name matches "Intel(R) Xeon(R) Processor @ " From 8b09bdd3c2f8aa98b2e3693ff59eaa70c843e985 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 15:38:51 +0000 Subject: [PATCH 371/464] test: Skip CPUID.(EAX=1FH,ECX=2) in test_cpu_config_dump_vs_actual CPUID leaf 1FH is a preferred superset to CPUID leaf 0BH. For the same reason as CPUID leaf 0BH, the subleaf 2 should be skipped if guest userspace cpuid command enumerates it. Signed-off-by: Takahiro Itazuri --- .../integration_tests/functional/test_cpu_template_helper.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_template_helper.py b/tests/integration_tests/functional/test_cpu_template_helper.py index 1b1c2478da3..0c0e09d1a60 100644 --- a/tests/integration_tests/functional/test_cpu_template_helper.py +++ b/tests/integration_tests/functional/test_cpu_template_helper.py @@ -133,6 +133,10 @@ def build_cpu_config_dict(cpu_config_path): # support it, the userspace cpuid command in ubuntu 22 reports not only # the subleaf 0 but also the subleaf 1. (0x1B, 0x1), + # CPUID.1Fh is a preferred superset to CPUID.0Bh. For the same reason as + # CPUID.Bh, the subleaf 2 should be skipped when the guest userspace cpuid + # enumerates it. + (0x1F, 0x2), # CPUID.20000000h is not documented in Intel SDM and AMD APM. KVM doesn't # report it, but the userspace cpuid command in ubuntu 22 does. (0x20000000, 0x0), From f1f7794b0732770a8e886f2555bba6c8ebf75d87 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 16:08:21 +0000 Subject: [PATCH 372/464] test: Skip MSR 0xE1 in test_cpu_config_dump_vs_actual The MSR is R/W and guest OS modifies it after boot to control UMWAIT feature. Signed-off-by: Takahiro Itazuri --- tests/integration_tests/functional/test_cpu_template_helper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_template_helper.py b/tests/integration_tests/functional/test_cpu_template_helper.py index 0c0e09d1a60..b6b6bf69dc8 100644 --- a/tests/integration_tests/functional/test_cpu_template_helper.py +++ b/tests/integration_tests/functional/test_cpu_template_helper.py @@ -188,6 +188,9 @@ def build_cpu_config_dict(cpu_config_path): 0x48, # MSR_IA32_SMBASE is not accessible outside of System Management Mode. 0x9E, + # MSR_IA32_UMWAIT_CONTROL is R/W MSR that guest OS modifies after boot to + # control UMWAIT feature. + 0xE1, # MSR_IA32_TSX_CTRL is R/W MSR to disable Intel TSX feature as a mitigation # against TAA vulnerability. 0x122, From 3bc126de2eabacb7c7da13c62c42021215e92382 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 13 Mar 2025 16:14:10 +0000 Subject: [PATCH 373/464] test: Skip MSR 0x1C4 in test_cpu_config_dump_vs_actual MSR_IA32_XFD is R/W MSR for guest OS to control which XSAVE-enabled features are temporarily disabled. Guest OS disables TILEDATA by default using the MSR. Signed-off-by: Takahiro Itazuri --- .../integration_tests/functional/test_cpu_template_helper.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_template_helper.py b/tests/integration_tests/functional/test_cpu_template_helper.py index b6b6bf69dc8..6ff2db1f7f0 100644 --- a/tests/integration_tests/functional/test_cpu_template_helper.py +++ b/tests/integration_tests/functional/test_cpu_template_helper.py @@ -200,6 +200,10 @@ def build_cpu_config_dict(cpu_config_path): 0x174, 0x175, 0x176, + # MSR_IA32_XFD is R/W MSR for guest OS to control which XSAVE-enabled + # features are temporarily disabled. Guest OS disables TILEDATA by default + # using the MSR. + 0x1C4, # MSR_IA32_TSC_DEADLINE specifies the time at which a timer interrupt # should occur and depends on the elapsed time. 0x6E0, From f4d6aa516918a80805fd536af57f01f112f5295e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Tue, 11 Mar 2025 06:42:10 +0000 Subject: [PATCH 374/464] test: Use any guest kernels in test_host_vs_guest_cpu_features CPU features that guest kernel can vary depending on its kernel version. Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_host_vs_guest.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 c8075faa505..8f42ebe02cf 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 @@ -157,10 +157,12 @@ } -def test_host_vs_guest_cpu_features(uvm_nano): +def test_host_vs_guest_cpu_features(uvm_plain_any): """Check CPU features host vs guest""" - vm = uvm_nano + vm = uvm_plain_any + vm.spawn() + vm.basic_config() vm.add_net_iface() vm.start() host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split()) From 165b20d92f8fe3edb2017eb5c12d532cbd18907c Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Tue, 11 Mar 2025 06:40:55 +0000 Subject: [PATCH 375/464] test: test_host_vs_guest_cpu_features on Intel Sapphire Rapids Intel Sapphire Rapids has some new features compared to older Intel processors. Some of them are just not virtualized by KVM, others started to be passed through to guests since specific kernel versions, and the others can be emulated but now supported by hardware. Signed-off-by: Takahiro Itazuri --- .../test_cpu_features_host_vs_guest.py | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) 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 8f42ebe02cf..e387018d6d2 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 @@ -233,6 +233,102 @@ def test_host_vs_guest_cpu_features(uvm_plain_any): assert host_feats - guest_feats == host_guest_diff_6_1 assert guest_feats - host_feats == INTEL_GUEST_ONLY_FEATS - {"umip"} + case CpuModel.INTEL_SAPPHIRE_RAPIDS: + expected_host_minus_guest = INTEL_HOST_ONLY_FEATS.copy() + expected_guest_minus_host = INTEL_GUEST_ONLY_FEATS.copy() + + host_version = global_props.host_linux_version_tpl + guest_version = vm.guest_kernel_version + + # KVM does not support virtualization of the following hardware features yet for several + # reasons (e.g. security, simply difficulty of implementation). + expected_host_minus_guest |= { + # Intel Total Memory Encryption (TME) is the capability to encrypt the entirety of + # physical memory of a system. TME is enabled by system BIOS/hardware and applies to + # the phyiscal memory as a whole. + "tme", + # PCONFIG instruction allows software to configure certain platform features. It + # supports these features with multiple leaf functions, selecting a leaf function + # using the value in EAX. As of this writing, the only defined PCONFIG leaf function + # is for key programming for total memory encryption-multi-key (TME-MK). + "pconfig", + # Architectural Last Branch Record (Arch LBR) that is a feature that logs the most + # recently executed branch instructions (e.g. source and destination addresses). + # Traditional LBR implementations have existed in Intel CPUs for years and the MSR + # interface varied by CPU model. Arch LBR is a standardized version. There is a + # kernel patch created in 2022 but didn't get merged due to a mess. + # https://lore.kernel.org/all/20221125040604.5051-1-weijiang.yang@intel.com/ + "arch_lbr", + # ENQCMD/ENQCMDS are instructions that allow software to atomically write 64-byte + # commands to enqueue registers, which are special device registers accessed using + # memory-mapped I/O. + "enqcmd", + # Intel Resource Director Technology (RDT) feature set provides a set of allocation + # (resource control) capabilities including Cache Allocation Technology (CAT) and + # Code and Data Prioritization (CDP). + # L3 variants are listed in INTEL_HOST_ONLY_FEATS. + "cat_l2", + "cdp_l2", + # This is a synthesized bit for split lock detection that raise an Alignment Check + # (#AC) exception if an operand of an atomic operation crosses two cache lines. It + # is not enumerated on CPUID, instead detected by actually attempting to read from + # MSR address 0x33 (MSR_MEMORY_CTRL in Intel SDM, MSR_TEST_CTRL in Linux kernel). + "split_lock_detect", + } + + # The following features are also not virtualized by KVM yet but are only supported on + # newer kernel versions. + if host_version >= (5, 18): + expected_host_minus_guest |= { + # Hardware Feedback Interface (HFI) is a feature that gives OSes a performance + # and energy efficiency capability data for each CPU that can be used to + # influence task placement decisions. + # https://github.com/torvalds/linux/commit/7b8f40b3de75c971a4e5f9308b06deb59118dbac + "hfi", + # Indirect Brach Tracking (IBT) is a feature where the CPU ensures that indirect + # branch targets start with ENDBRANCH instruction (`endbr32` or `endbr64`), + # which executes as a no-op; if anything else is found, a control-protection + # (#CP) fault will be raised. + # https://github.com/torvalds/linux/commit/991625f3dd2cbc4b787deb0213e2bcf8fa264b21 + "ibt", + } + + # AVX512 FP16 is supported and passed through on v5.11+. + # https://github.com/torvalds/linux/commit/e1b35da5e624f8b09d2e98845c2e4c84b179d9a4 + # https://github.com/torvalds/linux/commit/2224fc9efb2d6593fbfb57287e39ba4958b188ba + if host_version >= (5, 11) and guest_version < (5, 11): + expected_host_minus_guest |= {"avx512_fp16"} + + # AVX VNNI support is supported and passed through on v5.12+. + # https://github.com/torvalds/linux/commit/b85a0425d8056f3bd8d0a94ecdddf2a39d32a801 + # https://github.com/torvalds/linux/commit/1085a6b585d7d1c441cd10fdb4c7a4d96a22eba7 + if host_version >= (5, 12) and guest_version < (5, 12): + expected_host_minus_guest |= {"avx_vnni"} + + # Bus lock detection is supported on v5.12+ and passed through on v5.13+. + # https://github.com/torvalds/linux/commit/f21d4d3b97a8603567e5d4250bd75e8ebbd520af + # https://github.com/torvalds/linux/commit/76ea438b4afcd9ee8da3387e9af4625eaccff58f + if host_version >= (5, 13) and guest_version < (5, 12): + expected_host_minus_guest |= {"bus_lock_detect"} + + # Intel AMX is supported and passed through on v5.17+. + # https://github.com/torvalds/linux/commit/690a757d610e50c2c3acd2e4bc3992cfc63feff2 + if host_version >= (5, 17) and guest_version < (5, 17): + expected_host_minus_guest |= {"amx_bf16", "amx_int8", "amx_tile"} + + expected_guest_minus_host -= { + # UMIP can be emulated by KVM on Intel processors, but is supported in hardware on + # Intel Sapphire Rapids and passed through. + "umip", + # This is a synthesized bit and it is always set on guest thanks to kvm-clock. But + # Intel Sapphire Rapids reports TSC frequency on CPUID leaf 0x15, so the bit is also + # set on host. + "tsc_known_freq", + } + + assert host_feats - guest_feats == expected_host_minus_guest + assert guest_feats - host_feats == expected_guest_minus_host + case CpuModel.ARM_NEOVERSE_N1: expected_guest_minus_host = set() expected_host_minus_guest = set() From 983a20a42c777c673edecca67b45b9947edd73f9 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Wed, 12 Mar 2025 11:55:40 +0000 Subject: [PATCH 376/464] test: Ignore REPTAR on Intel Sapphire Rapids REPTAR is reported "vulnerable" inside guest on Intel Sapphire Rapids for the same reason as Intel Ice Lake (microcode versio not exposed to guests). Signed-off-by: Takahiro Itazuri --- tests/integration_tests/security/test_vulnerabilities.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index 14307e56888..356bdb4370f 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -85,7 +85,10 @@ def expected_vulnerabilities(self, cpu_template_name): Since we have a test on host and the exception in guest is not valid, we add a check to ignore this exception. """ - if global_props.cpu_codename == "INTEL_ICELAKE" and cpu_template_name is None: + if ( + global_props.cpu_codename in ["INTEL_ICELAKE", "INTEL_SAPPHIRE_RAPIDS"] + and cpu_template_name is None + ): return { '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}' } From b41a64ca592df084b7e31e3d659e141f8acf4fcb Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 10:51:42 +0000 Subject: [PATCH 377/464] chore: Use Amazon Linux 2023 for per-arch step No reason to use an older platform. Signed-off-by: Takahiro Itazuri --- .buildkite/common.py | 2 +- .buildkite/pipeline_pr.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index 4bacff75f1e..f936bbce314 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -256,7 +256,7 @@ def __init__(self, with_build_step=True, **kwargs): self.per_instance = overlay_dict(per_instance, args.step_param) self.per_arch = self.per_instance.copy() self.per_arch["instances"] = ["m6i.metal", "m7g.metal"] - self.per_arch["platforms"] = [("al2", "linux_5.10")] + self.per_arch["platforms"] = [("al2023", "linux_6.1")] self.binary_dir = args.binary_dir # Build sharing if with_build_step: diff --git a/.buildkite/pipeline_pr.py b/.buildkite/pipeline_pr.py index 5943b92e327..7f85f777c6b 100755 --- a/.buildkite/pipeline_pr.py +++ b/.buildkite/pipeline_pr.py @@ -59,7 +59,7 @@ # Kani step default # Kani runs fastest on m6a.metal instances=["m6a.metal", "m7g.metal"], - platforms=[("al2", "linux_5.10")], + platforms=[("al2023", "linux_6.1")], timeout_in_minutes=300, **DEFAULTS_PERF, depends_on_build=False, From 25ba9cf9faf71d90d070321a409548d10f69ba3a Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 09:19:00 +0000 Subject: [PATCH 378/464] chore: Make any instances acceptable in fingerprint test Similar to other buildkite pipeline generation script, we would like to inject an onboarding instance type via --instances arg. Signed-off-by: Takahiro Itazuri --- .buildkite/pipeline_cpu_template.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py index c8c5f75fa09..f5af7e8693c 100755 --- a/.buildkite/pipeline_cpu_template.py +++ b/.buildkite/pipeline_cpu_template.py @@ -6,7 +6,7 @@ from enum import Enum -from common import DEFAULT_INSTANCES, DEFAULT_PLATFORMS, BKPipeline, group +from common import DEFAULT_PLATFORMS, BKPipeline, group class BkStep(str, Enum): @@ -34,7 +34,6 @@ class BkStep(str, Enum): "tools/devtool -y test --no-build -- -m no_block_pr integration_tests/functional/test_cpu_template_helper.py -k test_guest_cpu_config_change", ], BkStep.LABEL: "🖐️ fingerprint", - "instances": DEFAULT_INSTANCES, "platforms": DEFAULT_PLATFORMS, }, "cpuid_wrmsr": { From 9b76935fe42c48e6e8da4f3212f41940e7d08b2e Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 09:24:46 +0000 Subject: [PATCH 379/464] chore: Make any platforms acceptable in CPU template test It's not necessary at the moment, but we will want to test new platform (new Amazon Linux) in the future by injecting via --platforms arg. Signed-off-by: Takahiro Itazuri --- .buildkite/pipeline_cpu_template.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py index f5af7e8693c..18cf0cad3f5 100755 --- a/.buildkite/pipeline_cpu_template.py +++ b/.buildkite/pipeline_cpu_template.py @@ -27,14 +27,12 @@ class BkStep(str, Enum): ], BkStep.LABEL: "📖 rdmsr", "instances": ["c5n.metal", "m5n.metal", "m6a.metal", "m6i.metal"], - "platforms": DEFAULT_PLATFORMS, }, "fingerprint": { BkStep.COMMAND: [ "tools/devtool -y test --no-build -- -m no_block_pr integration_tests/functional/test_cpu_template_helper.py -k test_guest_cpu_config_change", ], BkStep.LABEL: "🖐️ fingerprint", - "platforms": DEFAULT_PLATFORMS, }, "cpuid_wrmsr": { "snapshot": { From 8c60d91fce200a81d6bf1553967cbb31a16eeee7 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 09:57:47 +0000 Subject: [PATCH 380/464] chore: Add fingerprint of Intel Sapphire Rapids to track change of guest-visible CPU features. Signed-off-by: Takahiro Itazuri --- ...rprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json | 1434 +++++++++++++++ ...erprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json | 1534 +++++++++++++++++ 2 files changed, 2968 insertions(+) create mode 100644 tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json create mode 100644 tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json new file mode 100644 index 00000000000..18006227938 --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json @@ -0,0 +1,1434 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", + "microcode_version": "0x2b000620", + "bios_version": "1.0", + "bios_revision": "3.3", + "guest_cpu_config": { + "kvm_capabilities": [], + "cpuid_modifiers": [ + { + "leaf": "0x0", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000011111" + }, + { + "register": "ebx", + "bitmap": "0b01110101011011100110010101000111" + }, + { + "register": "ecx", + "bitmap": "0b01101100011001010111010001101110" + }, + { + "register": "edx", + "bitmap": "0b01001001011001010110111001101001" + } + ] + }, + { + "leaf": "0x1", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000010000000011011111000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000010000100000000000" + }, + { + "register": "ecx", + "bitmap": "0b11110111111110100011001000100011" + }, + { + "register": "edx", + "bitmap": "0b00001111100010111111101111111111" + } + ] + }, + { + "leaf": "0x2", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000111111101111111100000001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000011110000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "0b00000010110000000000000000111111" + }, + { + "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": "0b00000000000000000000011111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x4", + "subleaf": "0x3", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101100011" + }, + { + "register": "ebx", + "bitmap": "0b00000011100000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000011011111111111111" + }, + { + "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": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b11110001101111110010011111101011" + }, + { + "register": "ecx", + "bitmap": "0b00011010010000010101111101101110" + }, + { + "register": "edx", + "bitmap": "0b10101100000000010100010000010000" + } + ] + }, + { + "leaf": "0x7", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000100000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "0b00000000000000000000001011100111" + }, + { + "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": "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": "0x17", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x18", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x19", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1d", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1e", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1f", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000100000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1f", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000101" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000001000000001" + }, + { + "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": "0b00000000000000000111001001101111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000004", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "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": "0b00001000000000000111000001000000" + }, + { + "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": "0b00000000000000000011100100101110" + }, + { + "register": "ebx", + "bitmap": "0b00000001000000001101001000000000" + }, + { + "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": "0xe1", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x10a", + "bitmap": "0b0000000000000000000000000000000000001100000010001110000011101011" + }, + { + "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": "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_SAPPHIRE_RAPIDS_6.1host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json new file mode 100644 index 00000000000..f4244459112 --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json @@ -0,0 +1,1534 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", + "microcode_version": "0x2b000620", + "bios_version": "1.0", + "bios_revision": "3.3", + "guest_cpu_config": { + "kvm_capabilities": [], + "cpuid_modifiers": [ + { + "leaf": "0x0", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000011111" + }, + { + "register": "ebx", + "bitmap": "0b01110101011011100110010101000111" + }, + { + "register": "ecx", + "bitmap": "0b01101100011001010111010001101110" + }, + { + "register": "edx", + "bitmap": "0b01001001011001010110111001101001" + } + ] + }, + { + "leaf": "0x1", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000010000000011011111000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000010000100000000000" + }, + { + "register": "ecx", + "bitmap": "0b11110111111110100011001000100011" + }, + { + "register": "edx", + "bitmap": "0b00001111100010111111101111111111" + } + ] + }, + { + "leaf": "0x2", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000111111101111111100000001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000011110000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "0b00000010110000000000000000111111" + }, + { + "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": "0b00000000000000000000011111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x4", + "subleaf": "0x3", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101100011" + }, + { + "register": "ebx", + "bitmap": "0b00000011100000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000011011111111111111" + }, + { + "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": "0b00000000000000000000000000000010" + }, + { + "register": "ebx", + "bitmap": "0b11110001101111110010011111101011" + }, + { + "register": "ecx", + "bitmap": "0b00011011010000010101111101101110" + }, + { + "register": "edx", + "bitmap": "0b10101111110000010100010000010000" + } + ] + }, + { + "leaf": "0x7", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000110000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x7", + "subleaf": "0x2", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000010111" + } + ] + }, + { + "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": "0b00000000000001100000001011100111" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001001000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000010101100000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000011111" + }, + { + "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": "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": "0xd", + "subleaf": "0x11", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000001000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000101011000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000010" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x12", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000010000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000101100000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000110" + }, + { + "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": "0x17", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x18", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x19", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1d", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1d", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000100000000000010000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000010000000000001000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000010000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1e", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000100000000010000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1f", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000100000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x1f", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000101" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000001000000001" + }, + { + "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": "0b00000000000000000111001001101111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000004", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "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": "0b00001000000000000111000001000000" + }, + { + "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": "0b00000000000000000011100100101110" + }, + { + "register": "ebx", + "bitmap": "0b00000001000000001101001000000000" + }, + { + "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": "0xe1", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x10a", + "bitmap": "0b0000000000000000000000000000000000001100000010001110000011101011" + }, + { + "addr": "0x140", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x174", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x175", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x176", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x1a0", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "addr": "0x1c4", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x1c5", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x1fc", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x277", + "bitmap": "0b0000000000000111000001000000011000000000000001110000010000000110" + }, + { + "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 From 36f6222b9ac041ce1754ffb524b32371e5cb7245 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 10:11:00 +0000 Subject: [PATCH 381/464] chore: Add fingerprint of AMD Genoa to track changes of guest-visible CPU features Signed-off-by: Takahiro Itazuri --- .../fingerprint_AMD_GENOA_5.10host.json | 1591 ++++++++++++++++ .../fingerprint_AMD_GENOA_6.1host.json | 1641 +++++++++++++++++ 2 files changed, 3232 insertions(+) create mode 100644 tests/data/cpu_template_helper/fingerprint_AMD_GENOA_5.10host.json create mode 100644 tests/data/cpu_template_helper/fingerprint_AMD_GENOA_6.1host.json diff --git a/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_5.10host.json b/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_5.10host.json new file mode 100644 index 00000000000..7b835e165b8 --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_5.10host.json @@ -0,0 +1,1591 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", + "microcode_version": "0xa101154", + "bios_version": "1.0", + "bios_revision": "2.19", + "guest_cpu_config": { + "kvm_capabilities": [], + "cpuid_modifiers": [ + { + "leaf": "0x0", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000010000" + }, + { + "register": "ebx", + "bitmap": "0b01101000011101000111010101000001" + }, + { + "register": "ecx", + "bitmap": "0b01000100010011010100000101100011" + }, + { + "register": "edx", + "bitmap": "0b01101001011101000110111001100101" + } + ] + }, + { + "leaf": "0x1", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000101000010000111100010001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000010000100000000000" + }, + { + "register": "ecx", + "bitmap": "0b11110111111110100011001000000011" + }, + { + "register": "edx", + "bitmap": "0b00000111100010111111101111111111" + } + ] + }, + { + "leaf": "0x2", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "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": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b11110001101111110000011110101011" + }, + { + "register": "ecx", + "bitmap": "0b00000000010000010101111101001110" + }, + { + "register": "edx", + "bitmap": "0b10001100000000000000000000010000" + } + ] + }, + { + "leaf": "0x7", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000100000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "0b00000000000000000000001011100111" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001001000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000100110001000" + }, + { + "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": "0x5", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000001000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001101000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x6", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000001000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001110000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x7", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000010000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000010110000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x9", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000001000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000100110000000" + }, + { + "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": "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": "0b10000000000000000000000000011111" + }, + { + "register": "ebx", + "bitmap": "0b01101000011101000111010101000001" + }, + { + "register": "ecx", + "bitmap": "0b01000100010011010100000101100011" + }, + { + "register": "edx", + "bitmap": "0b01101001011101000110111001100101" + } + ] + }, + { + "leaf": "0x80000001", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000101000010000111100010001" + }, + { + "register": "ebx", + "bitmap": "0b01000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000110000000000001111110111" + }, + { + "register": "edx", + "bitmap": "0b00101111110100111111101111111111" + } + ] + }, + { + "leaf": "0x80000002", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00100000010001000100110101000001" + }, + { + "register": "ebx", + "bitmap": "0b01000011010110010101000001000101" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000003", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000004", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000005", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b11111111010010001111111101000000" + }, + { + "register": "ebx", + "bitmap": "0b11111111010010001111111101000000" + }, + { + "register": "ecx", + "bitmap": "0b00100000000010000000000101000000" + }, + { + "register": "edx", + "bitmap": "0b00100000000010000000000101000000" + } + ] + }, + { + "leaf": "0x80000006", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b01011100000000000010001000000000" + }, + { + "register": "ebx", + "bitmap": "0b01101100000000000100001000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000100000000000110000101000000" + }, + { + "register": "edx", + "bitmap": "0b00001100000000001001000101000000" + } + ] + }, + { + "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": "0b00000000000000000011100100110100" + }, + { + "register": "ebx", + "bitmap": "0b00000011000000101101001000000101" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000111000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000009", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000001000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000001001" + } + ] + }, + { + "leaf": "0x8000000b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000d", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000e", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000f", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000010", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000011", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000012", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000013", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000014", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000015", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000016", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000017", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000018", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000019", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b11110000010010001111000001000000" + }, + { + "register": "ebx", + "bitmap": "0b11110000010000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000110" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000100100001" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000100100010" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x2", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101000011" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000011111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000010" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x3", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101100011" + }, + { + "register": "ebx", + "bitmap": "0b00000011110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000111111111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000001" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x4", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001e", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001f", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000011000011111111111111111011" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000100000110110011" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000001111101110" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000001111101111" + } + ] + } + ], + "msr_modifiers": [ + { + "addr": "0x11", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x12", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x34", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x3b", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x48", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x8b", + "bitmap": "0b0000000000000000000000000000000000000001000000000000000001100101" + }, + { + "addr": "0x9e", + "bitmap": "0b0000000000000000000000000000000000000000000000110000000000000000" + }, + { + "addr": "0xce", + "bitmap": "0b0000000000000000000000000000000010000000000000000000000000000000" + }, + { + "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": "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" + }, + { + "addr": "0xc0010117", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0xc001011f", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + } + ] + } +} \ No newline at end of file diff --git a/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_6.1host.json b/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_6.1host.json new file mode 100644 index 00000000000..0a096b62831 --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_AMD_GENOA_6.1host.json @@ -0,0 +1,1641 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", + "microcode_version": "0xa101154", + "bios_version": "1.0", + "bios_revision": "2.19", + "guest_cpu_config": { + "kvm_capabilities": [], + "cpuid_modifiers": [ + { + "leaf": "0x0", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000010000" + }, + { + "register": "ebx", + "bitmap": "0b01101000011101000111010101000001" + }, + { + "register": "ecx", + "bitmap": "0b01000100010011010100000101100011" + }, + { + "register": "edx", + "bitmap": "0b01101001011101000110111001100101" + } + ] + }, + { + "leaf": "0x1", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000101000010000111100010001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000010000100000000000" + }, + { + "register": "ecx", + "bitmap": "0b11110111111110100011001000000011" + }, + { + "register": "edx", + "bitmap": "0b00000111100010111111101111111111" + } + ] + }, + { + "leaf": "0x2", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "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": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b11110001101111110000011110101011" + }, + { + "register": "ecx", + "bitmap": "0b00000000010000010101111101001110" + }, + { + "register": "edx", + "bitmap": "0b10001100000000000000000000010000" + } + ] + }, + { + "leaf": "0x7", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000100000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "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": "0b00000000000000000000001011100111" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001001000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000100110001000" + }, + { + "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": "0x5", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000001000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001101000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x6", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000001000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000001110000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x7", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000010000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000010110000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0xd", + "subleaf": "0x9", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000001000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000100110000000" + }, + { + "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": "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": "0b10000000000000000000000000100001" + }, + { + "register": "ebx", + "bitmap": "0b01101000011101000111010101000001" + }, + { + "register": "ecx", + "bitmap": "0b01000100010011010100000101100011" + }, + { + "register": "edx", + "bitmap": "0b01101001011101000110111001100101" + } + ] + }, + { + "leaf": "0x80000001", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000101000010000111100010001" + }, + { + "register": "ebx", + "bitmap": "0b01000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000110000000000001111110111" + }, + { + "register": "edx", + "bitmap": "0b00101111110100111111101111111111" + } + ] + }, + { + "leaf": "0x80000002", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00100000010001000100110101000001" + }, + { + "register": "ebx", + "bitmap": "0b01000011010110010101000001000101" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000003", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000004", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000005", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b11111111010010001111111101000000" + }, + { + "register": "ebx", + "bitmap": "0b11111111010010001111111101000000" + }, + { + "register": "ecx", + "bitmap": "0b00100000000010000000000101000000" + }, + { + "register": "edx", + "bitmap": "0b00100000000010000000000101000000" + } + ] + }, + { + "leaf": "0x80000006", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b01011100000000000010001000000000" + }, + { + "register": "ebx", + "bitmap": "0b01101100000000000100001000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000100000000000110000101000000" + }, + { + "register": "edx", + "bitmap": "0b00001100000000001001000101000000" + } + ] + }, + { + "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": "0b00000000000000000011100100110100" + }, + { + "register": "ebx", + "bitmap": "0b00010011000000101101001000000101" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000111000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000009", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000001" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000001000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00010000000000011001010000111011" + } + ] + }, + { + "leaf": "0x8000000b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000d", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000e", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000000f", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000010", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000011", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000012", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000013", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000014", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000015", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000016", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000017", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000018", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000019", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b11110000010010001111000001000000" + }, + { + "register": "ebx", + "bitmap": "0b11110000010000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001a", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000110" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001b", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001c", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x0", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000100100001" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x1", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000100100010" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x2", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101000011" + }, + { + "register": "ebx", + "bitmap": "0b00000001110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000011111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000010" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x3", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000101100011" + }, + { + "register": "ebx", + "bitmap": "0b00000011110000000000000000111111" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000111111111111111" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000001" + } + ] + }, + { + "leaf": "0x8000001d", + "subleaf": "0x4", + "flags": 1, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001e", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x8000001f", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000020", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + }, + { + "leaf": "0x80000021", + "subleaf": "0x0", + "flags": 0, + "modifiers": [ + { + "register": "eax", + "bitmap": "0b00000000000000000000000001000101" + }, + { + "register": "ebx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "ecx", + "bitmap": "0b00000000000000000000000000000000" + }, + { + "register": "edx", + "bitmap": "0b00000000000000000000000000000000" + } + ] + } + ], + "msr_modifiers": [ + { + "addr": "0x11", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x12", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x34", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x3b", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x48", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x8b", + "bitmap": "0b0000000000000000000000000000000000000001000000000000000001100101" + }, + { + "addr": "0x9e", + "bitmap": "0b0000000000000000000000000000000000000000000000110000000000000000" + }, + { + "addr": "0xce", + "bitmap": "0b0000000000000000000000000000000010000000000000000000000000000000" + }, + { + "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": "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": "0xc0000104", + "bitmap": "0b0000000000000000000000000000000100000000000000000000000000000000" + }, + { + "addr": "0xc0010015", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0xc0010117", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0xc001011f", + "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" + } + ] + } +} \ No newline at end of file From 3476905df5e567f6db7afdd7aa645293f9d615fb Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 10:14:44 +0000 Subject: [PATCH 382/464] chore: Add fingerprint of Graviton4 to track changes of guest-visible CPU features. Signed-off-by: Takahiro Itazuri --- .../fingerprint_ARM_NEOVERSE_V2_5.10host.json | 1261 +++++++++++++++++ .../fingerprint_ARM_NEOVERSE_V2_6.1host.json | 981 +++++++++++++ 2 files changed, 2242 insertions(+) create mode 100644 tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_5.10host.json create mode 100644 tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_6.1host.json diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_5.10host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_5.10host.json new file mode 100644 index 00000000000..89dbb773a09 --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_5.10host.json @@ -0,0 +1,1261 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.aarch64", + "microcode_version": "0x0000000000000017", + "bios_version": "1.0", + "bios_revision": "1.0", + "guest_cpu_config": { + "kvm_capabilities": [], + "vcpu_features": [], + "reg_modifiers": [ + { + "addr": "0x60200000001000d4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60200000001000d5", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6020000000110000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011010" + }, + { + "addr": "0x6020000000110001", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011010" + }, + { + "addr": "0x6020000000110002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111010" + }, + { + "addr": "0x6030000000100000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000111111000000000000000000000" + }, + { + "addr": "0x6030000000100002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100004", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100008", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100018", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100020", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100022", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100028", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100030", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100032", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100042", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000101" + }, + { + "addr": "0x6030000000100044", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100046", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100048", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100050", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138004", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138005", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138007", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138015", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138017", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138025", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138027", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138035", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138037", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138044", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138045", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138046", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138047", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138054", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138055", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138056", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138057", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138064", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138065", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138066", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138067", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138074", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138075", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138076", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138077", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013a038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001000011111101010011110001" + }, + { + "addr": "0x603000000013c005", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000" + }, + { + "addr": "0x603000000013c006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010111" + }, + { + "addr": "0x603000000013c008", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c009", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c011", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c013", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c015", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c017", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c018", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c019", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c020", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001000100000001000000010001000000100011000100010001000100010001" + }, + { + "addr": "0x603000000013c021", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100001" + }, + { + "addr": "0x603000000013c022", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c023", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c025", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c027", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c028", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111001000010000001100000101010000001001" + }, + { + "addr": "0x603000000013c029", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c030", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001001000100001000100000000000100010000001000010010000100100000" + }, + { + "addr": "0x603000000013c031", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000010001000100010001000100000000001000010001000000000010" + }, + { + "addr": "0x603000000013c032", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c033", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c035", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c037", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010001000000000000100000001000100100101" + }, + { + "addr": "0x603000000013c039", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000001100010010000100100010" + }, + { + "addr": "0x603000000013c03a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001001000100001000000010001000100010010000100000001000000010001" + }, + { + "addr": "0x603000000013c03b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c080", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110001010000000001111000" + }, + { + "addr": "0x603000000013c081", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c082", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c100", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c101", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c102", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c288", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c289", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c290", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c300", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c3a0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c4f1", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c4f2", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c510", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c518", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c600", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c609", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c681", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c684", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c708", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c801", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000010000000000000000000100011" + }, + { + "addr": "0x603000000013c807", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013d000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013d801", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010110100010001001100000000000100" + }, + { + "addr": "0x603000000013dce0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000011101100" + }, + { + "addr": "0x603000000013dce1", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dce2", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dce3", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dce4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dce5", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dce8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013dcf0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013dcf3", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013de82", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013de83", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df02", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013df19", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df40", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df41", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df42", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df43", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df44", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df45", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df46", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df47", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df48", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df49", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df4f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df50", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df51", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df52", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df53", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df54", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df55", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df56", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df57", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df58", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df59", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df5a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df5b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df5c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df5d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df5e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df60", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df61", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df62", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df63", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df64", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df65", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df66", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df67", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df68", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df69", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df6f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df70", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df71", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df72", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df73", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df74", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df75", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df76", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df77", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df78", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df79", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df7f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013e180", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013e281", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013e298", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100000000" + }, + { + "addr": "0x6030000000140000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000" + }, + { + "addr": "0x6030000000140001", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010" + }, + { + "addr": "0x6030000000140002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000140003", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010" + }, + { + "addr": "0x6040000000100054", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100058", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010005c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100060", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100064", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100068", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010006c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100070", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100074", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100078", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010007c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100080", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100084", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100088", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010008c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100090", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100094", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100098", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010009c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000ac", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000bc", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000cc", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000d0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ] + } +} \ No newline at end of file diff --git a/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_6.1host.json b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_6.1host.json new file mode 100644 index 00000000000..2e05a08356c --- /dev/null +++ b/tests/data/cpu_template_helper/fingerprint_ARM_NEOVERSE_V2_6.1host.json @@ -0,0 +1,981 @@ +{ + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.aarch64", + "microcode_version": "0x0000000000000017", + "bios_version": "1.0", + "bios_revision": "1.0", + "guest_cpu_config": { + "kvm_capabilities": [], + "vcpu_features": [], + "reg_modifiers": [ + { + "addr": "0x60200000001000d4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60200000001000d5", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6020000000110000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011010" + }, + { + "addr": "0x6020000000110001", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011010" + }, + { + "addr": "0x6020000000110002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111010" + }, + { + "addr": "0x6030000000100000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000111111000000000000000000000" + }, + { + "addr": "0x6030000000100002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100004", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100008", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010000e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100018", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010001e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100020", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100022", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100028", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010002e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100030", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100032", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010003e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100042", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000101" + }, + { + "addr": "0x6030000000100044", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100046", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100048", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000010004e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000100050", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138004", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138005", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138007", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013800f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138015", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138017", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013801f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138025", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138027", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013802f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138035", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138037", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013803f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138044", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138045", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138046", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138047", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013804f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138054", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138055", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138056", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138057", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013805f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138064", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138065", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138066", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138067", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013806f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138074", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138075", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138076", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000138077", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013807f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013808c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000" + }, + { + "addr": "0x603000000013a038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001000011111101010011110001" + }, + { + "addr": "0x603000000013c005", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000" + }, + { + "addr": "0x603000000013c006", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010111" + }, + { + "addr": "0x603000000013c008", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c009", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c00f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c010", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c011", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c012", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c013", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c014", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c015", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c016", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c017", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c018", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c019", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c01f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c020", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001000100000001000000010001000000100001000100010001000100010001" + }, + { + "addr": "0x603000000013c021", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100001" + }, + { + "addr": "0x603000000013c022", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c023", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c024", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c025", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c026", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c027", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c028", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000010000001100000101000000000110" + }, + { + "addr": "0x603000000013c029", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c02f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c030", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001001000100001000100000000000100010000001000010010000100100000" + }, + { + "addr": "0x603000000013c031", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000010001000100010001000100000000001000010001000000000010" + }, + { + "addr": "0x603000000013c032", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c033", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c034", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c035", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c036", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c037", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c038", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010001000000000000100000001000100100101" + }, + { + "addr": "0x603000000013c039", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000001100010010000100100010" + }, + { + "addr": "0x603000000013c03a", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001001000100001000000010001000100010010000000000001000000010001" + }, + { + "addr": "0x603000000013c03b", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03d", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03e", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c03f", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c080", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110001010000000001111000" + }, + { + "addr": "0x603000000013c081", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c082", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c100", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c101", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c102", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c288", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c289", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c290", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c300", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c3a0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c510", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c518", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c600", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c609", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c681", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c684", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013c708", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013c801", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000010000000000000000000100011" + }, + { + "addr": "0x603000000013c807", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013d000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013d801", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010110100010001001100000000000100" + }, + { + "addr": "0x603000000013de82", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013de83", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013df02", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013df11", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013df12", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x603000000013df19", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100" + }, + { + "addr": "0x603000000013e180", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013e281", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000001110111100111111011000111111011011011101011011100000011011110" + }, + { + "addr": "0x603000000013e298", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100000000" + }, + { + "addr": "0x6030000000140000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001" + }, + { + "addr": "0x6030000000140001", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010" + }, + { + "addr": "0x6030000000140002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6030000000140003", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010" + }, + { + "addr": "0x6030000000160000", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + }, + { + "addr": "0x6030000000160001", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + }, + { + "addr": "0x6030000000160002", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011" + }, + { + "addr": "0x6040000000100054", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100058", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010005c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100060", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100064", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100068", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010006c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100070", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100074", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100078", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010007c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100080", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100084", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100088", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010008c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100090", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100094", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x6040000000100098", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x604000000010009c", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000a8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000ac", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000b8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000bc", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c4", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000c8", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000cc", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "addr": "0x60400000001000d0", + "bitmap": "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ] + } +} \ No newline at end of file From 4e9b2155266f0cb7b25523e40a15b272d2d73fbb Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 14 Mar 2025 15:22:02 +0000 Subject: [PATCH 383/464] chore: Regather fingerprints for x86-64 instance types We changed to calculate the right-shift bits to address socket ID based on max number of vCPUs, but I forgot to update fingerprints :( Fixes: 62207118 ("fix(vmm): Calc right-shift bits to address socket ID") Signed-off-by: Takahiro Itazuri --- .../fingerprint_AMD_MILAN_5.10host.json | 10 +++++----- .../fingerprint_AMD_MILAN_6.1host.json | 12 ++++++------ .../fingerprint_INTEL_CASCADELAKE_5.10host.json | 10 +++++----- .../fingerprint_INTEL_CASCADELAKE_6.1host.json | 10 +++++----- .../fingerprint_INTEL_ICELAKE_5.10host.json | 10 +++++----- .../fingerprint_INTEL_ICELAKE_6.1host.json | 10 +++++----- .../fingerprint_INTEL_SKYLAKE_5.10host.json | 8 ++++---- .../fingerprint_INTEL_SKYLAKE_6.1host.json | 8 ++++---- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_5.10host.json b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_5.10host.json index 5501ca88ce4..d24260ad7fa 100644 --- a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_5.10host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.214-202.855.amzn2.x86_64", - "microcode_version": "0xa0011d1", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", + "microcode_version": "0xa0011db", "bios_version": "1.0", - "bios_revision": "0.69", + "bios_revision": "0.90", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -290,7 +290,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", diff --git a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json index 56f406560ee..5dca6763099 100644 --- a/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_AMD_MILAN_6.1host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.x86_64", - "microcode_version": "0xa0011d1", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", + "microcode_version": "0xa0011db", "bios_version": "1.0", - "bios_revision": "0.69", + "bios_revision": "0.90", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -290,7 +290,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", @@ -1546,4 +1546,4 @@ } ] } -} +} \ No newline at end of file diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json index 8568992dcef..45e3d7ed4b8 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.215-203.850.amzn2.x86_64", - "microcode_version": "0x5003604", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", + "microcode_version": "0x5003801", "bios_version": "1.0", - "bios_revision": "3.80", + "bios_revision": "4.11", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -382,7 +382,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_6.1host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_6.1host.json index fc9ee8dddf8..1dc7abee252 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_6.1host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.x86_64", - "microcode_version": "0x5003604", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", + "microcode_version": "0x5003801", "bios_version": "1.0", - "bios_revision": "3.80", + "bios_revision": "4.11", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -382,7 +382,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json index 3a6c8d5123e..5bf57d51da9 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.215-203.850.amzn2.x86_64", - "microcode_version": "0xd0003b9", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", + "microcode_version": "0xd0003f6", "bios_version": "1.0", - "bios_revision": "1.36", + "bios_revision": "1.40", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -405,7 +405,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_6.1host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_6.1host.json index d307c491d2a..05dea2e484a 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_ICELAKE_6.1host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.x86_64", - "microcode_version": "0xd0003b9", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", + "microcode_version": "0xd0003f6", "bios_version": "1.0", - "bios_revision": "1.36", + "bios_revision": "1.40", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -428,7 +428,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", 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 index c80924adefa..d6eb7d0a478 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "5.10.215-203.850.amzn2.x86_64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "5.10.234-225.910.amzn2.x86_64", "microcode_version": "0x2007006", "bios_version": "1.0", - "bios_revision": "3.80", + "bios_revision": "4.11", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -382,7 +382,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", 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 index 324619e3268..432a97f64bc 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_6.1host.json @@ -1,9 +1,9 @@ { - "firecracker_version": "1.8.0-dev", - "kernel_version": "6.1.84-99.169.amzn2023.x86_64", + "firecracker_version": "1.12.0-dev", + "kernel_version": "6.1.129-138.220.amzn2023.x86_64", "microcode_version": "0x2007006", "bios_version": "1.0", - "bios_revision": "3.80", + "bios_revision": "4.11", "guest_cpu_config": { "kvm_capabilities": [], "cpuid_modifiers": [ @@ -382,7 +382,7 @@ "modifiers": [ { "register": "eax", - "bitmap": "0b00000000000000000000000000000111" + "bitmap": "0b00000000000000000000000000000101" }, { "register": "ebx", From 200a955d84ee22eb207162f49e37b95ecf2591d2 Mon Sep 17 00:00:00 2001 From: Andrew Laucius Date: Wed, 14 Aug 2024 11:27:37 -0400 Subject: [PATCH 384/464] Adding host device renaming for snapshot restore In some scenarios it is not possible to use the jailer, especially in limited privilege environments where the security is external to firecracker itself. But in these cases a snapshot may have to use a different tap device than the one that it was using when it was snapshotted. Signed-off-by: Andrew Laucius Signed-off-by: Babis Chalios --- .../src/api_server/request/snapshot.rs | 5 ++++ src/firecracker/swagger/firecracker.yaml | 24 +++++++++++++++++++ src/vmm/src/devices/virtio/net/persist.rs | 4 ++-- src/vmm/src/persist.rs | 18 +++++++++++++- src/vmm/src/rpc_interface.rs | 1 + src/vmm/src/vmm_config/snapshot.rs | 15 ++++++++++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/firecracker/src/api_server/request/snapshot.rs b/src/firecracker/src/api_server/request/snapshot.rs index 37a66f80093..0f92468cec9 100644 --- a/src/firecracker/src/api_server/request/snapshot.rs +++ b/src/firecracker/src/api_server/request/snapshot.rs @@ -105,6 +105,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result { mem_backend, enable_diff_snapshots: snapshot_config.enable_diff_snapshots, resume_vm: snapshot_config.resume_vm, + network_overrides: snapshot_config.network_overrides, }; // Construct the `ParsedRequest` object. @@ -181,6 +182,7 @@ mod tests { }, enable_diff_snapshots: false, resume_vm: false, + network_overrides: vec![], }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); assert!( @@ -210,6 +212,7 @@ mod tests { }, enable_diff_snapshots: true, resume_vm: false, + network_overrides: vec![], }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); assert!( @@ -239,6 +242,7 @@ mod tests { }, enable_diff_snapshots: false, resume_vm: true, + network_overrides: vec![], }; let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); assert!( @@ -265,6 +269,7 @@ mod tests { }, enable_diff_snapshots: false, resume_vm: true, + network_overrides: vec![], }; let parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); assert_eq!( diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index de6d1e3da40..480141d322f 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -1216,6 +1216,24 @@ definitions: Type of snapshot to create. It is optional and by default, a full snapshot is created. + NetworkOverride: + type: object + description: + Allows for changing the backing TAP device of a network interface + during snapshot restore. + required: + - iface_id + - host_dev_name + properties: + iface_id: + type: string + description: + The name of the interface to modify + host_dev_name: + type: string + description: + The new host device of the interface + SnapshotLoadParams: type: object description: @@ -1247,6 +1265,12 @@ definitions: type: boolean description: When set to true, the vm is also resumed if the snapshot load is successful. + network_overrides: + type: array + description: Network host device names to override + items: + $ref: "#/definitions/NetworkOverride" + TokenBucket: type: object diff --git a/src/vmm/src/devices/virtio/net/persist.rs b/src/vmm/src/devices/virtio/net/persist.rs index 66493f0f334..5f2d6f560b4 100644 --- a/src/vmm/src/devices/virtio/net/persist.rs +++ b/src/vmm/src/devices/virtio/net/persist.rs @@ -55,8 +55,8 @@ impl RxBufferState { /// at snapshot. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct NetState { - id: String, - tap_if_name: String, + pub id: String, + pub tap_if_name: String, rx_rate_limiter_state: RateLimiterState, tx_rate_limiter_state: RateLimiterState, /// The associated MMDS network stack. diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 91a29909590..95616972247 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -405,7 +405,21 @@ pub fn restore_from_snapshot( params: &LoadSnapshotParams, vm_resources: &mut VmResources, ) -> Result>, RestoreFromSnapshotError> { - let microvm_state = snapshot_state_from_file(¶ms.snapshot_path)?; + let mut microvm_state = snapshot_state_from_file(¶ms.snapshot_path)?; + for entry in ¶ms.network_overrides { + let net_devices = &mut microvm_state.device_states.net_devices; + if let Some(device) = net_devices + .iter_mut() + .find(|x| x.device_state.id == entry.iface_id) + { + device + .device_state + .tap_if_name + .clone_from(&entry.host_dev_name); + } else { + return Err(SnapshotStateFromFileError::UnknownNetworkDevice.into()); + } + } let track_dirty_pages = params.enable_diff_snapshots; let vcpu_count = microvm_state @@ -480,6 +494,8 @@ pub enum SnapshotStateFromFileError { Meta(std::io::Error), /// Failed to load snapshot state from file: {0} Load(#[from] crate::snapshot::SnapshotError), + /// Unknown Network Device. + UnknownNetworkDevice, } fn snapshot_state_from_file( diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 3aca3e2a6f0..8eb7227347a 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -1269,6 +1269,7 @@ mod tests { }, enable_diff_snapshots: false, resume_vm: false, + network_overrides: vec![], }, ))); check_unsupported(runtime_request(VmmAction::SetEntropyDevice( diff --git a/src/vmm/src/vmm_config/snapshot.rs b/src/vmm/src/vmm_config/snapshot.rs index e1850b74939..27a7841d5a4 100644 --- a/src/vmm/src/vmm_config/snapshot.rs +++ b/src/vmm/src/vmm_config/snapshot.rs @@ -47,6 +47,16 @@ pub struct CreateSnapshotParams { pub mem_file_path: PathBuf, } +/// Allows for changing the mapping between tap devices and host devices +/// during snapshot restore +#[derive(Debug, PartialEq, Eq, Deserialize)] +pub struct NetworkOverride { + /// The index of the interface to modify + pub iface_id: String, + /// The new name of the interface to be assigned + pub host_dev_name: String, +} + /// Stores the configuration that will be used for loading a snapshot. #[derive(Debug, PartialEq, Eq)] pub struct LoadSnapshotParams { @@ -60,6 +70,8 @@ pub struct LoadSnapshotParams { /// When set to true, the vm is also resumed if the snapshot load /// is successful. pub resume_vm: bool, + /// The network devices to override on load. + pub network_overrides: Vec, } /// Stores the configuration for loading a snapshot that is provided by the user. @@ -82,6 +94,9 @@ pub struct LoadSnapshotConfig { /// Whether or not to resume the vm post snapshot load. #[serde(default)] pub resume_vm: bool, + /// The network devices to override on load. + #[serde(default)] + pub network_overrides: Vec, } /// Stores the configuration used for managing snapshot memory. From f0d233d656372608917109ac8a7397c843b3c11b Mon Sep 17 00:00:00 2001 From: Andrew Laucius Date: Wed, 14 Aug 2024 16:29:00 -0400 Subject: [PATCH 385/464] Tests for snapshot network renames Test that we can correctly parse configuration and API calls in a backwards compatible way. Signed-off-by: Andrew Laucius Signed-off-by: Babis Chalios --- .../src/api_server/request/snapshot.rs | 41 ++++++++++++++++++- src/vmm/tests/integration_tests.rs | 2 + tests/framework/microvm.py | 17 ++++++++ .../functional/test_snapshot_basic.py | 29 +++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/firecracker/src/api_server/request/snapshot.rs b/src/firecracker/src/api_server/request/snapshot.rs index 0f92468cec9..4a96292d11d 100644 --- a/src/firecracker/src/api_server/request/snapshot.rs +++ b/src/firecracker/src/api_server/request/snapshot.rs @@ -121,7 +121,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result { #[cfg(test)] mod tests { - use vmm::vmm_config::snapshot::{MemBackendConfig, MemBackendType}; + use vmm::vmm_config::snapshot::{MemBackendConfig, MemBackendType, NetworkOverride}; use super::*; use crate::api_server::parsed_request::tests::{depr_action_from_req, vmm_action_from_request}; @@ -256,6 +256,45 @@ mod tests { VmmAction::LoadSnapshot(expected_config) ); + let body = r#"{ + "snapshot_path": "foo", + "mem_backend": { + "backend_path": "bar", + "backend_type": "Uffd" + }, + "resume_vm": true, + "network_overrides": [ + { + "iface_id": "eth0", + "host_dev_name": "vmtap2" + } + ] + }"#; + let expected_config = LoadSnapshotParams { + snapshot_path: PathBuf::from("foo"), + mem_backend: MemBackendConfig { + backend_path: PathBuf::from("bar"), + backend_type: MemBackendType::Uffd, + }, + enable_diff_snapshots: false, + resume_vm: true, + network_overrides: vec![NetworkOverride { + iface_id: String::from("eth0"), + host_dev_name: String::from("vmtap2"), + }], + }; + let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap(); + assert!( + parsed_request + .parsing_info() + .take_deprecation_message() + .is_none() + ); + assert_eq!( + vmm_action_from_request(parsed_request), + VmmAction::LoadSnapshot(expected_config) + ); + let body = r#"{ "snapshot_path": "foo", "mem_file_path": "bar", diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index bb0ac5f3240..7fe2c80d35d 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -261,6 +261,7 @@ fn verify_load_snapshot(snapshot_file: TempFile, memory_file: TempFile) { }, enable_diff_snapshots: false, resume_vm: true, + network_overrides: vec![], })) .unwrap(); @@ -344,6 +345,7 @@ fn verify_load_snap_disallowed_after_boot_resources(res: VmmAction, res_name: &s }, enable_diff_snapshots: false, resume_vm: false, + network_overrides: vec![], }); let err = preboot_api_controller.handle_preboot_request(req); assert!( diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 7d2e9002822..d3a5fdceaf9 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -974,6 +974,7 @@ def restore_from_snapshot( snapshot: Snapshot, resume: bool = False, uffd_path: Path = None, + rename_interfaces: dict = None, ): """Restore a snapshot""" jailed_snapshot = snapshot.copy_to_chroot(Path(self.chroot())) @@ -1001,11 +1002,27 @@ def restore_from_snapshot( # Adjust things just in case self.kernel_file = Path(self.kernel_file) + iface_overrides = [] + if rename_interfaces is not None: + iface_overrides = [ + {"iface_id": k, "host_dev_name": v} + for k, v in rename_interfaces.items() + ] + + optional_kwargs = {} + if iface_overrides: + # For backwards compatibility ab testing we want to avoid adding + # new parameters until we have a release baseline with the new + # parameter. Once the release baseline has moved, this assignment + # can be inline in the snapshot_load command below + optional_kwargs["network_overrides"] = iface_overrides + self.api.snapshot_load.put( mem_backend=mem_backend, snapshot_path=str(jailed_vmstate), enable_diff_snapshots=snapshot.is_diff, resume_vm=resume, + **optional_kwargs, ) # This is not a "wait for boot", but rather a "VM still works after restoration" if snapshot.net_ifaces and resume: diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index bedaae488f6..cf20354bcce 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Basic tests scenarios for snapshot save/restore.""" +import dataclasses import filecmp import logging import os @@ -9,12 +10,14 @@ import re import shutil import time +import uuid from pathlib import Path import pytest import host_tools.cargo_build as host import host_tools.drive as drive_tools +import host_tools.network as net_tools from framework import utils from framework.microvm import SnapshotType from framework.properties import global_props @@ -570,3 +573,29 @@ def test_physical_counter_reset_aarch64(uvm_nano): break else: raise RuntimeError("Did not find CNTPCT_EL0 register in snapshot") + + +def test_snapshot_rename_interface(uvm_nano, microvm_factory): + """ + Test that we can restore a snapshot and point its interface to a + different host interface. + """ + vm = uvm_nano + base_iface = vm.add_net_iface() + vm.start() + snapshot = vm.snapshot_full() + + # We don't reuse the network namespace as it may conflict with + # previous/future devices + restored_vm = microvm_factory.build(netns=net_tools.NetNs(str(uuid.uuid4()))) + # Override the tap name, but keep the same IP configuration + iface_override = dataclasses.replace(base_iface, tap_name="tap_override") + + restored_vm.spawn() + snapshot.net_ifaces.clear() + snapshot.net_ifaces.append(iface_override) + restored_vm.restore_from_snapshot( + snapshot, + rename_interfaces={iface_override.dev_name: iface_override.tap_name}, + resume=True, + ) From 7c7884ce37950968d4f2bbfd3aff354015251ca3 Mon Sep 17 00:00:00 2001 From: Andrew Laucius Date: Thu, 15 Aug 2024 17:32:54 -0400 Subject: [PATCH 386/464] Adding documentation and changelog Documenting the ability to rename network interfaces on snapshot restore. Signed-off-by: Andrew Laucius Signed-off-by: Babis Chalios --- CHANGELOG.md | 2 + docs/snapshotting/network-for-clones.md | 57 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b904f448b6b..a3bf8ea3c55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to - [#5065](https://github.com/firecracker-microvm/firecracker/pull/5065) Added support for Intel AMX (Advanced Matrix Extensions). +- [#4731](https://github.com/firecracker-microvm/firecracker/pull/4731): Added + support for modifying the host TAP device name during snapshot restore. ### Changed diff --git a/docs/snapshotting/network-for-clones.md b/docs/snapshotting/network-for-clones.md index b997ba3687e..df99f782e38 100644 --- a/docs/snapshotting/network-for-clones.md +++ b/docs/snapshotting/network-for-clones.md @@ -142,6 +142,63 @@ Otherwise, packets originating from the guest might be using old Link Layer Address for up to arp cache timeout seconds. After said timeout period, connectivity will work both ways even without an explicit flush. +### Renaming host device names + +In some environments where the jailer is not being used, restoring a snapshot +may be tricky because the tap device on the host will not be the same as the tap +device that the original VM was mapped to when it was snapshotted, for example +when the tap device comes from a pool of such devices. + +In this case you can use the `network_overrides` parameter of the snapshot +restore API to specify which guest network device maps to which host tap device. + +For example, if we have a network interface named `eth0` in the snapshotted +microVM, we can override it to point to the host device `vmtap01` during +snapshot resume, like this: + +```bash +curl --unix-socket /tmp/firecracker.socket -i \ + -X PUT 'http://localhost/snapshot/load' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "snapshot_path": "./snapshot_file", + "mem_backend": { + "backend_path": "./mem_file", + "backend_type": "File" + }, + "network_overrides": [ + { + "iface_id": "eth0", + "host_dev_name": "vmtap01" + } + ] + }' +``` + +This may require reconfiguration of the networking inside the VM so that it is +still routable externally. +[network setup documentation](../network-setup.md#in-the-guest) describes what +the typical setup is. If you are not using network namespaces or the jailer, +then the guest will have to be made aware (via vsock or other channel) that it +needs to reconfigure its network to match the network configured on the tap +device. + +If the new TAP device, say `vmtap3` has been configured to use a guest address +of `172.16.3.2` then after snapshot restore you would run something like: + +```bash +# In the guest + +# Clear out the previous addr and route +ip addr flush dev eth0 +ip route flush dev eth0 + +# Configure the new address +ip addr add 172.16.3.2/30 dev eth0 +ip route add default via 172.16.3.1/30 dev eth0 +``` + # Ingress connectivity The above setup only provides egress connectivity. If in addition we also want From b4117e57a4168da7815c6172c7aecca3de1f3a31 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 17 Mar 2025 10:52:50 +0000 Subject: [PATCH 387/464] feat: Add m7a as a tested instance Adding M7a to our default tested intances and the cross snapshot pipeline. Update the README to reflect this change. Signed-off-by: Jack Thomson --- .buildkite/common.py | 1 + .buildkite/pipeline_cross.py | 8 +++++++- README.md | 17 +++++++++-------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.buildkite/common.py b/.buildkite/common.py index f936bbce314..24607609841 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -19,6 +19,7 @@ "m5n.metal", # Intel Cascade Lake "m6i.metal", # Intel Icelake "m6a.metal", # AMD Milan + "m7a.metal-48xl", # AMD Genoa "m6g.metal", # Graviton2 "m7g.metal", # Graviton3 ] diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index 1bac8c4bc3b..c611f87c065 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -18,7 +18,13 @@ per_instance = pipeline.per_instance.copy() per_instance.pop("instances") per_instance.pop("platforms") - instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"] + instances_x86_64 = [ + "c5n.metal", + "m5n.metal", + "m6i.metal", + "m6a.metal", + "m7a.metal-48xl", + ] instances_aarch64 = ["m7g.metal"] commands = [ "./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py", diff --git a/README.md b/README.md index 5805b76ba15..dcb5771f994 100644 --- a/README.md +++ b/README.md @@ -130,14 +130,15 @@ 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 | | | | -| m6a.metal | | | | -| m6g.metal | | | | -| m7g.metal | | | | +| 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 | | | | +| m6a.metal | | | | +| m7a.metal-48xl | | | | +| m6g.metal | | | | +| m7g.metal | | | | ## Known issues and Limitations From 9d58501c9fbb44a208e57292a18d2bc4f6756ba2 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 17 Mar 2025 11:01:02 +0000 Subject: [PATCH 388/464] test: Ignore m7a tcp throughput We are investigating volatility in the tcp throughput on m7a for now we will ignore it, until we find a solution. Signed-off-by: Jack Thomson --- tools/ab_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ab_test.py b/tools/ab_test.py index 7c4cdcada7a..fdcb433fe1b 100755 --- a/tools/ab_test.py +++ b/tools/ab_test.py @@ -44,6 +44,8 @@ IGNORED = [ # Network throughput on m6a.metal {"instance": "m6a.metal", "performance_test": "test_network_tcp_throughput"}, + # Network throughput on m7a.metal + {"instance": "m7a.metal-48xl", "performance_test": "test_network_tcp_throughput"}, ] From a6b0188707135109bef822ad0fd0168279bd0159 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 17 Mar 2025 12:01:25 +0000 Subject: [PATCH 389/464] doc: Add AMD Genoa support to changelog New entry in the changelog for AMD Genoa that is officially onboarded and tested on Firecracker Signed-off-by: Jack Thomson --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3bf8ea3c55..935c1b65b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ and this project adheres to provides the appropriate ELF Note to indicate that PVH boot mode is supported. Linux kernels newer than 5.0 compiled with `CONFIG_PVH=y` set this ELF Note, as do FreeBSD kernels. +- [#5088](https://github.com/firecracker-microvm/firecracker/pull/5088): Added + AMD Genoa as a supported and tested platform for Firecracker. ### Changed From c9fa6fec686cbf5da39b57133c6eb0921ba5b94f Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Mon, 17 Mar 2025 13:45:56 +0000 Subject: [PATCH 390/464] test: Add m7a to cpu template pipeline Add m7a to the cpu template pipeline and add msr baselines for the variant. Signed-off-by: Jack Thomson --- .buildkite/pipeline_cpu_template.py | 16 +- ..._list_T2A_AMD_GENOA_5.10host_5.10guest.csv | 298 +++++++++++++++++ ...r_list_T2A_AMD_GENOA_5.10host_6.1guest.csv | 298 +++++++++++++++++ ...r_list_T2A_AMD_GENOA_6.1host_5.10guest.csv | 300 ++++++++++++++++++ ...sr_list_T2A_AMD_GENOA_6.1host_6.1guest.csv | 300 ++++++++++++++++++ 5 files changed, 1210 insertions(+), 2 deletions(-) create mode 100644 tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_5.10guest.csv create mode 100644 tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_6.1guest.csv create mode 100644 tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_5.10guest.csv create mode 100644 tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_6.1guest.csv diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py index 18cf0cad3f5..e42ae926d2e 100755 --- a/.buildkite/pipeline_cpu_template.py +++ b/.buildkite/pipeline_cpu_template.py @@ -26,7 +26,13 @@ class BkStep(str, Enum): "tools/devtool -y test --no-build -- -m nonci -n4 --dist worksteal integration_tests/functional/test_cpu_features_x86_64.py -k 'test_cpu_rdmsr' " ], BkStep.LABEL: "📖 rdmsr", - "instances": ["c5n.metal", "m5n.metal", "m6a.metal", "m6i.metal"], + "instances": [ + "c5n.metal", + "m5n.metal", + "m6i.metal", + "m6a.metal", + "m7a.metal-48xl", + ], }, "fingerprint": { BkStep.COMMAND: [ @@ -59,7 +65,13 @@ class BkStep(str, Enum): "c5n.metal": ["m5n.metal", "m6i.metal"], "m6i.metal": ["m5n.metal", "c5n.metal"], }, - "instances": ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"], + "instances": [ + "c5n.metal", + "m5n.metal", + "m6i.metal", + "m6a.metal", + "m7a.metal-48xl", + ], }, } diff --git a/tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_5.10guest.csv b/tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_5.10guest.csv new file mode 100644 index 00000000000..82f8d2673d7 --- /dev/null +++ b/tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_5.10guest.csv @@ -0,0 +1,298 @@ +MSR_ADDR,VALUE +0,0x0 +0x1,0x0 +0x10,0x86e8ca1e +0x11,0x24a1008 +0x12,0x24a2001 +0x17,0x0 +0x1b,0xfee00d00 +0x2a,0x0 +0x2c,0x1000000 +0x34,0x0 +0x3b,0x0 +0x48,0x0 +0x8b,0x1000065 +0xc1,0x0 +0xc2,0x0 +0xcd,0x3 +0xce,0x80000000 +0xfe,0x508 +0x11e,0xbe702111 +0x140,0x0 +0x174,0x10 +0x175,0xfffffe0000003000 +0x176,0xffffffff81a01510 +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,0x150b49126 +0x802,0x0 +0x803,0x50014 +0x808,0x10 +0x80a,0x10 +0x80d,0x1 +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 +0x830,0x0 +0x832,0x400ec +0x833,0x10000 +0x834,0x400 +0x835,0x10700 +0x836,0x400 +0x837,0xfe +0x838,0x0 +0x839,0x0 +0x83e,0x0 +0xc0000080,0xd01 +0xc0000081,0x23001000000000 +0xc0000082,0xffffffff81a00080 +0xc0000083,0xffffffff81a015c0 +0xc0000084,0x47700 +0xc0000100,0x7fbe30c03740 +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 +0xc0010114,0x0 +0xc0010117,0x0 +0xc001011f,0x0 +0xc0010131,0x0 +0xc0010140,0x4 +0xc0010141,0x0 +0xc0010200,0x0 +0xc0010201,0x0 +0xc0010202,0x0 +0xc0010203,0x0 +0xc0010204,0x0 +0xc0010205,0x0 +0xc0010206,0x0 +0xc0010207,0x0 +0xc0010208,0x0 +0xc0010209,0x0 +0xc001020a,0x0 +0xc001020b,0xffff +0xc0011021,0x0 +0xc0011022,0x0 +0xc0011023,0x0 +0xc0011029,0x2 +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_T2A_AMD_GENOA_5.10host_6.1guest.csv b/tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_6.1guest.csv new file mode 100644 index 00000000000..cbb1af0b3ac --- /dev/null +++ b/tests/data/msr/msr_list_T2A_AMD_GENOA_5.10host_6.1guest.csv @@ -0,0 +1,298 @@ +MSR_ADDR,VALUE +0,0x0 +0x1,0x0 +0x10,0x7cc4d24c +0x11,0x25cb008 +0x12,0x25cc001 +0x17,0x0 +0x1b,0xfee00d00 +0x2a,0x0 +0x2c,0x1000000 +0x34,0x0 +0x3b,0x0 +0x48,0x0 +0x8b,0x1000065 +0xc1,0x0 +0xc2,0x0 +0xcd,0x3 +0xce,0x80000000 +0xfe,0x508 +0x11e,0xbe702111 +0x140,0x0 +0x174,0x10 +0x175,0xfffffe0000003000 +0x176,0xffffffff81a01620 +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,0x13998e6da +0x802,0x0 +0x803,0x50014 +0x808,0x10 +0x80a,0x10 +0x80d,0x1 +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 +0x830,0x0 +0x832,0x400ec +0x833,0x10000 +0x834,0x400 +0x835,0x10700 +0x836,0x400 +0x837,0xfe +0x838,0x0 +0x839,0x0 +0x83e,0x0 +0xc0000080,0xd01 +0xc0000081,0x23001000000000 +0xc0000082,0xffffffff81a00080 +0xc0000083,0xffffffff81a016e0 +0xc0000084,0x257fd5 +0xc0000100,0x7f2345db1740 +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 +0xc0010114,0x0 +0xc0010117,0x0 +0xc001011f,0x0 +0xc0010131,0x0 +0xc0010140,0x4 +0xc0010141,0x0 +0xc0010200,0x0 +0xc0010201,0x0 +0xc0010202,0x0 +0xc0010203,0x0 +0xc0010204,0x0 +0xc0010205,0x0 +0xc0010206,0x0 +0xc0010207,0x0 +0xc0010208,0x0 +0xc0010209,0x0 +0xc001020a,0x0 +0xc001020b,0xffff +0xc0011021,0x0 +0xc0011022,0x0 +0xc0011023,0x0 +0xc0011029,0x2 +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_T2A_AMD_GENOA_6.1host_5.10guest.csv b/tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_5.10guest.csv new file mode 100644 index 00000000000..b3015830e3f --- /dev/null +++ b/tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_5.10guest.csv @@ -0,0 +1,300 @@ +MSR_ADDR,VALUE +0,0x0 +0x1,0x0 +0x10,0x916c8f40 +0x11,0x24a1008 +0x12,0x24a2001 +0x17,0x0 +0x1b,0xfee00d00 +0x2a,0x0 +0x2c,0x1000000 +0x34,0x0 +0x3b,0x0 +0x48,0x0 +0x8b,0x1000065 +0xc1,0x0 +0xc2,0x0 +0xcd,0x3 +0xce,0x80000000 +0xfe,0x508 +0x11e,0xbe702111 +0x140,0x0 +0x174,0x10 +0x175,0x3000 +0x176,0x81a01510 +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,0x13b260b8c +0x802,0x0 +0x803,0x50014 +0x808,0x10 +0x80a,0x10 +0x80d,0x1 +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 +0x830,0x0 +0x832,0x400ec +0x833,0x10000 +0x834,0x400 +0x835,0x10700 +0x836,0x400 +0x837,0xfe +0x838,0x0 +0x839,0x0 +0x83e,0x0 +0xc0000080,0xd01 +0xc0000081,0x23001000000000 +0xc0000082,0xffffffff81a00080 +0xc0000083,0xffffffff81a015c0 +0xc0000084,0x47700 +0xc0000100,0x7f4e13140740 +0xc0000101,0xffff88803ec00000 +0xc0000102,0x0 +0xc0000103,0x0 +0xc0000104,0x100000000 +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 +0xc0010114,0x0 +0xc0010117,0x0 +0xc001011f,0x0 +0xc0010130,0x0 +0xc0010131,0x0 +0xc0010140,0x4 +0xc0010141,0x0 +0xc0010200,0x0 +0xc0010201,0x0 +0xc0010202,0x0 +0xc0010203,0x0 +0xc0010204,0x0 +0xc0010205,0x0 +0xc0010206,0x0 +0xc0010207,0x0 +0xc0010208,0x0 +0xc0010209,0x0 +0xc001020a,0x0 +0xc001020b,0xffff +0xc0011021,0x0 +0xc0011022,0x0 +0xc0011023,0x0 +0xc0011029,0x2 +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_T2A_AMD_GENOA_6.1host_6.1guest.csv b/tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_6.1guest.csv new file mode 100644 index 00000000000..59606121fda --- /dev/null +++ b/tests/data/msr/msr_list_T2A_AMD_GENOA_6.1host_6.1guest.csv @@ -0,0 +1,300 @@ +MSR_ADDR,VALUE +0,0x0 +0x1,0x0 +0x10,0x7bd49b6c +0x11,0x25cb008 +0x12,0x25cc001 +0x17,0x0 +0x1b,0xfee00d00 +0x2a,0x0 +0x2c,0x1000000 +0x34,0x0 +0x3b,0x0 +0x48,0x0 +0x8b,0x1000065 +0xc1,0x0 +0xc2,0x0 +0xcd,0x3 +0xce,0x80000000 +0xfe,0x508 +0x11e,0xbe702111 +0x140,0x0 +0x174,0x10 +0x175,0x3000 +0x176,0x81a01620 +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,0x137e39322 +0x802,0x0 +0x803,0x50014 +0x808,0x10 +0x80a,0x10 +0x80d,0x1 +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 +0x830,0x0 +0x832,0x400ec +0x833,0x10000 +0x834,0x400 +0x835,0x10700 +0x836,0x400 +0x837,0xfe +0x838,0x0 +0x839,0x0 +0x83e,0x0 +0xc0000080,0xd01 +0xc0000081,0x23001000000000 +0xc0000082,0xffffffff81a00080 +0xc0000083,0xffffffff81a016e0 +0xc0000084,0x257fd5 +0xc0000100,0x7f7c57cd9740 +0xc0000101,0xffff88803ec00000 +0xc0000102,0x0 +0xc0000103,0x0 +0xc0000104,0x100000000 +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 +0xc0010114,0x0 +0xc0010117,0x0 +0xc001011f,0x0 +0xc0010130,0x0 +0xc0010131,0x0 +0xc0010140,0x4 +0xc0010141,0x0 +0xc0010200,0x0 +0xc0010201,0x0 +0xc0010202,0x0 +0xc0010203,0x0 +0xc0010204,0x0 +0xc0010205,0x0 +0xc0010206,0x0 +0xc0010207,0x0 +0xc0010208,0x0 +0xc0010209,0x0 +0xc001020a,0x0 +0xc001020b,0xffff +0xc0011021,0x0 +0xc0011022,0x0 +0xc0011023,0x0 +0xc0011029,0x2 +0xc001102a,0x0 +0xc001102c,0x0 +0x400000000,0x0 +0x2000000000,0x0 +0x4000000000,0x0 +0x8000000000,0x0 +0x1000000000000,0x0 +0x3c000000000000,0x0 +0x80000000000000,0x0 +0x40000000000000,0x0 From 431b829420f4902a20e76ca180956b0cc1a38a6c Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 17 Mar 2025 16:09:58 +0000 Subject: [PATCH 391/464] doc: update FAQ to stop saying we dont have ACPI We support ACPI nowadays. It doesn't change anything about this FAQ entry, because we don't implement power management using ACPI, but it still needs to be updated to actually say that. Signed-off-by: Patrick Roy --- FAQ.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FAQ.md b/FAQ.md index e2c011c3b7d..3ace710fc96 100644 --- a/FAQ.md +++ b/FAQ.md @@ -196,9 +196,9 @@ mapping: ### How can I gracefully reboot the guest? How can I gracefully poweroff the guest? -Firecracker does not implement ACPI and PM devices, therefore operations like -gracefully rebooting or powering off the guest are supported in unconventional -ways. +Firecracker does not virtualize guest power management, therefore operations +like gracefully rebooting or powering off the guest are supported in +unconventional ways. Running the `poweroff` or `halt` commands inside a Linux guest will bring it down but Firecracker process remains unaware of the guest shutdown so it lives From 888c5f3233cb0160d6f8cbe46d84199893b1acf0 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 18 Mar 2025 16:40:14 +0000 Subject: [PATCH 392/464] chore(doc): remove arm64 snapshot reg length limitation We fixed the arm register length limitation in #3787 but never removed this note from the doc. Signed-off-by: Egor Lazarchuk --- docs/snapshotting/snapshot-support.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index dc4235b6aad..18d3799da2d 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -126,17 +126,6 @@ The snapshot functionality is still in developer preview due to the following: ### Limitations -- Currently on aarch64 platforms only lower 128 bits of any register are saved - due to the limitations of `get/set_one_reg` from `kvm-ioctls` crate that - Firecracker uses to interact with KVM. This creates an issue with newer - aarch64 CPUs with support for registers with width greater than 128 bits, - because these registers will be truncated before being stored in the snapshot. - This can lead to uVM failure if restored from such snapshot. Because registers - wider than 128 bits are usually used in SVE instructions, the best way to - mitigate this issue is to ensure that the software run in uVM does not use SVE - instructions during snapshot creation. An alternative way is to use - [CPU templates](../cpu_templates/cpu-templates.md) to disable SVE related - features in uVM. - High snapshot latency on 5.4+ host kernels due to cgroups V1. We strongly recommend to deploy snapshots on cgroups V2 enabled hosts for the implied kernel versions - From 3db826fb1a480d6bc7585a6107a399ecfc46f1a8 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 12:27:10 +0000 Subject: [PATCH 393/464] doc: update quickstart guide to download latest artifacts We need to manually change what versions our quick start guide points to at every release. To avoid it getting behind, this change adds automatic detection of the CI artifacts related to the lastest version (which was already automatically detected). This means that CI artifacts will not point to the latest available but they will be the same we use to test the latest release, to ensure compatibility and that the guide always works. Signed-off-by: Riccardo Mancini --- docs/getting-started.md | 45 ++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 02a2077207b..04077292946 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -94,29 +94,44 @@ For simplicity, this guide will not use the [`jailer`](../src/jailer/). ### Getting a rootfs and Guest Kernel Image To successfully start a microVM, you will need an uncompressed Linux kernel -binary, and an ext4 file system image (to use as rootfs). This guide uses a 5.10 -kernel image with a Ubuntu 24.04 rootfs from our CI: +binary, and an ext4 file system image (to use as rootfs). This guide uses the +latest kernel image and Ubuntu rootfs available in our CI for the latest +release. ```bash ARCH="$(uname -m)" - -latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.11/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.11/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)") +release_url="https://github.com/firecracker-microvm/firecracker/releases" +latest_version=$(basename $(curl -fsSLI -o /dev/null -w %{url_effective} ${release_url}/latest)) +CI_VERSION=${latest_version%.*} +latest_kernel_key=$(curl "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/$CI_VERSION/$ARCH/vmlinux-&list-type=2" \ + | grep -oP "(?<=)(firecracker-ci/$CI_VERSION/$ARCH/vmlinux-[0-9]+\.[0-9]+\.[0-9]{1,3})(?=)" \ + | sort -V | tail -1) # Download a linux kernel binary -wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}" +wget "https://s3.amazonaws.com/spec.ccfc.min/${latest_kernel_key}" + +latest_ubuntu_key=$(curl "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/$CI_VERSION/$ARCH/ubuntu-&list-type=2" \ + | grep -oP "(?<=)(firecracker-ci/$CI_VERSION/$ARCH/ubuntu-[0-9]+\.[0-9]+\.squashfs)(?=)" \ + | sort -V | tail -1) +ubuntu_version=$(basename $latest_ubuntu_key .sqashfs | grep -oE '[0-9]+\.[0-9]+') # Download a rootfs -wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.11/${ARCH}/ubuntu-24.04.squashfs" +wget -O ubuntu-$ubuntu_version.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/$latest_ubuntu_key" # Create an ssh key for the rootfs -unsquashfs ubuntu-24.04.squashfs.upstream +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-24.04.id_rsa +mv -v id_rsa ./ubuntu-$ubuntu_version.id_rsa # create ext4 filesystem image sudo chown -R root:root squashfs-root -truncate -s 400M ubuntu-24.04.ext4 -sudo mkfs.ext4 -d squashfs-root -F ubuntu-24.04.ext4 +truncate -s 400M 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)" ``` ### Getting a Firecracker Binary @@ -241,7 +256,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ }" \ "http://localhost/boot-source" -ROOTFS="./ubuntu-24.04.ext4" +ROOTFS="./$(ls *.ext4 | tail -1)" # Set rootfs sudo curl -X PUT --unix-socket "${API_SOCKET}" \ @@ -282,14 +297,16 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ # started before we attempt to SSH into it. sleep 2s +KEY_NAME=./$(ls *.id_rsa | tail -1) + # Setup internet access in the guest -ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" +ssh -i $KEY_NAME root@172.16.0.2 "ip route add default via 172.16.0.1 dev eth0" # Setup DNS resolution in the guest -ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" +ssh -i $KEY_NAME root@172.16.0.2 "echo 'nameserver 8.8.8.8' > /etc/resolv.conf" # SSH into the microVM -ssh -i ./ubuntu-24.04.id_rsa root@172.16.0.2 +ssh -i $KEY_NAME root@172.16.0.2 # Use `root` for both the login and password. # Run `reboot` to exit. From b35ea2383d7bba3f70498d9f27e32e731773457a Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 15:41:10 +0000 Subject: [PATCH 394/464] chore(doc): clarify kernel policy and remove 4.14 The current wording is unclear since all kernel versions seem to be expired or to expire this year. This commit attempts to make it clear that 2 versions will always be supported. Furthermore, any reference to 4.14 is removed. Signed-off-by: Riccardo Mancini --- docs/kernel-policy.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/docs/kernel-policy.md b/docs/kernel-policy.md index 630b5fa1040..d609116054e 100644 --- a/docs/kernel-policy.md +++ b/docs/kernel-policy.md @@ -7,26 +7,31 @@ related changes. We are continuously validating the currently supported Firecracker releases (as per [Firecracker’s release policy](../docs/RELEASE_POLICY.md)) using a -combination of: - -- host linux kernel versions 5.10, and 6.1; -- guest linux kernel versions 5.10 and 6.1. Guest linux kernels 4.14 are - deprecated with Firecracker v1.9 and we will drop support for them with - Firecracker v1.10. +combination of all supported host and guest kernel versions in the table below. While other versions and other kernel configs might work, they are not periodically validated in our test suite, and using them might result in unexpected behaviour. Starting with release `v1.0` each major and minor release will specify the supported kernel versions. -Once a kernel version is officially enabled, it is supported for a **minimum of -2 years**. Adding support for a new kernel version will result in a Firecracker -release only if compatibility changes are required. +Once a kernel version is officially added, it is supported for a **minimum of 2 +years**. At least 2 major guest and host versions will be supported at any time. +When support is added for a third kernel version, the oldest will be deprecated +and removed in a following release, after its minimum end of support date. + +### Host Kernel + +| Host kernel | Min. version | Min. end of support | +| ----------: | -----------: | ------------------: | +| v5.10 | v1.0.0 | 2024-01-31 | +| v6.1 | v1.5.0 | 2025-10-12 | + +### Guest Kernel -| Host kernel | Guest kernel v4.14 (deprecated) | Guest kernel v5.10 | Guest kernel v6.1 | Min. end of support | -| ----------: | :-----------------------------: | :----------------: | :---------------: | ------------------: | -| v5.10 | Y (deprecated) | Y | Y | 2024-01-31 | -| v6.1 | Y (deprecated) | Y | Y | 2025-10-12 | +| Guest kernel | Min. version | Min. end of support | +| -----------: | -----------: | ------------------: | +| v5.10 | v1.0.0 | 2024-01-31 | +| v6.1 | v1.9.0 | 2026-09-02 | The guest kernel configs used in our validation pipelines can be found [here](../resources/guest_configs/) while a breakdown of the relevant guest From 27c91e8d9b22292c8929bbc7f269ea94393eb1ac Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 16:15:47 +0000 Subject: [PATCH 395/464] fix(release): fix release_notes.py We changed the markdown format of CHANGELOG.md to not have escapes for the square brackets, so the tool broke. This commit fixes it. Signed-off-by: Riccardo Mancini --- tools/release-notes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/release-notes.py b/tools/release-notes.py index 3c3731702e4..ea1019ddd3d 100755 --- a/tools/release-notes.py +++ b/tools/release-notes.py @@ -21,14 +21,14 @@ iterator = iter(changelog_lines) for line in iterator: - if line.startswith(f"## \\[{cur_version}\\]"): + if line.startswith(f"## [{cur_version}]"): break else: print(f"Could not find changelog entry for version {cur_version}!") sys.exit(1) for line in iterator: - if line.startswith("## \\["): + if line.startswith("## ["): break if line.startswith("#"): From 6b8a95b5c0cb3921084b64087965968e21f820a7 Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 15:55:22 +0000 Subject: [PATCH 396/464] chore(release): update release policy with 1.11 Add 1.11 to the release policy and mark 1.9 as unsupported. Signed-off-by: Riccardo Mancini --- docs/RELEASE_POLICY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/RELEASE_POLICY.md b/docs/RELEASE_POLICY.md index 3b6b8308d45..c9bd2a51089 100644 --- a/docs/RELEASE_POLICY.md +++ b/docs/RELEASE_POLICY.md @@ -90,8 +90,9 @@ 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.11 | 2025-03-18 | v1.11.0 | 2025-09-18 | Supported | | v1.10 | 2024-11-07 | v1.10.1 | 2025-05-07 | Supported | -| v1.9 | 2024-09-02 | v1.9.1 | 2025-03-02 | Supported | +| v1.9 | 2024-09-02 | v1.9.1 | 2025-03-02 | 2025-03-18 (v1.11 released) | | v1.8 | 2024-07-10 | v1.8.0 | 2025-01-10 | 2025-01-10 (end of 6mo support) | | v1.7 | 2024-03-18 | v1.7.0 | 2024-09-18 | 2024-09-18 (end of 6mo support) | | v1.6 | 2023-12-20 | v1.6.0 | 2024-06-20 | 2024-07-10 (v1.8 released) | From f40ed33d7368f6770f88b24cfd25f47a559595ba Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 16:26:24 +0000 Subject: [PATCH 397/464] fix(changelog): move PVH to unreleased section It was incorrectly marked as released in 1.11.0. Signed-off-by: Riccardo Mancini --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935c1b65b43..5759c8197d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to ### Added +- [#5048](https://github.com/firecracker-microvm/firecracker/pull/5048): Added + support for [PVH boot mode](docs/pvh.md). This is used when an x86 kernel + provides the appropriate ELF Note to indicate that PVH boot mode is supported. + Linux kernels newer than 5.0 compiled with `CONFIG_PVH=y` set this ELF Note, + as do FreeBSD kernels. - [#5065](https://github.com/firecracker-microvm/firecracker/pull/5065) Added support for Intel AMX (Advanced Matrix Extensions). - [#4731](https://github.com/firecracker-microvm/firecracker/pull/4731): Added @@ -38,11 +43,6 @@ and this project adheres to kernels. For older kernels physical counter will still be passed to the guest unmodified. See more info [here](https://github.com/firecracker-microvm/firecracker/blob/main/docs/prod-host-setup.md#arm-only-vm-physical-counter-behaviour) -- [#5048](https://github.com/firecracker-microvm/firecracker/pull/5048): Added - support for [PVH boot mode](docs/pvh.md). This is used when an x86 kernel - provides the appropriate ELF Note to indicate that PVH boot mode is supported. - Linux kernels newer than 5.0 compiled with `CONFIG_PVH=y` set this ELF Note, - as do FreeBSD kernels. - [#5088](https://github.com/firecracker-microvm/firecracker/pull/5088): Added AMD Genoa as a supported and tested platform for Firecracker. From 70d6e7f939ff33a9b0e43764f5877398267c935d Mon Sep 17 00:00:00 2001 From: Riccardo Mancini Date: Mon, 17 Mar 2025 16:34:28 +0000 Subject: [PATCH 398/464] chore(credits): cherry-pick updated credits from release branch This commit updates the CREDITS.md file to be in sync with the new release v1.11.0 Signed-off-by: Riccardo Mancini --- CREDITS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index 2610d0e2962..f8e68078dcc 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -36,6 +36,7 @@ Contributors to the Firecracker repository: - Alexandru Cihodaru - Alexandru-Cezar Sardan - Alin Dima +- Anatoli Babenia - Andrea Manzini - Andreea Florescu - Andrei Casu-Pop @@ -73,6 +74,7 @@ Contributors to the Firecracker repository: - Chris Christensen - Christian González - Christopher Diehl +- Christos Katsakioris - cneira - Colin Percival - Colton J. McCurdy @@ -125,6 +127,7 @@ Contributors to the Firecracker repository: - Iulian Barbu - Ives van Hoorne - Jack Thomson +- jackabald - James Curtis - James Turnbull - Javier Romero @@ -142,6 +145,7 @@ Contributors to the Firecracker repository: - Julian Stecklina - Justus Adam - Ján Mochňak +- kanpov - karthik nedunchezhiyan - KarthikVelayutham - Kazuyoshi Kato @@ -156,6 +160,7 @@ Contributors to the Firecracker repository: - Liviu Berciu - Lloyd - lloydmeta +- longxiangqiao - Lorenzo Fontana - LOU Xun - Lucas Zanela @@ -172,6 +177,7 @@ Contributors to the Firecracker repository: - Massimiliano Torromeo - Matias Teragni - Matt Wilson +- Matthew Buckingham-Bishop - Matthew Schlebusch - Max Wittek - Mehrdad Arshad Rad @@ -212,6 +218,7 @@ Contributors to the Firecracker repository: - Ria - Riccardo Mancini - Richard Case +- River Phillips - Rob Devereux - Robert Grimes - Rodrigue Chakode @@ -234,6 +241,7 @@ Contributors to the Firecracker repository: - Sripracha - Stefan Nita <32079871+stefannita01@users.noreply.github.com> - StemCll +- Steven Wirges - Sudan Landge - sundar.preston.789@gmail.com - Takahiro Itazuri @@ -245,6 +253,7 @@ Contributors to the Firecracker repository: - timvisee - Tobias Pfandzelter - Tomas Valenta +- tommady - Tomoya Iwata - Trăistaru Andrei Cristian - Tyler Anton From 07c07bd49e7c62fac76dcd1f98a7c4a76af08d83 Mon Sep 17 00:00:00 2001 From: acsmyth <54330152+acsmyth@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:57:19 +0000 Subject: [PATCH 399/464] fix: rename page_size_kib to page_size Keep around the old page_size_kib field, but add a deprecation notice. Signed-off-by: acsmyth <54330152+acsmyth@users.noreply.github.com> Co-authored-by: Patrick Roy Signed-off-by: Patrick Roy --- CHANGELOG.md | 7 +++++++ src/firecracker/examples/uffd/uffd_utils.rs | 13 +++++-------- src/vmm/src/persist.rs | 21 ++++++++++++++------- src/vmm/src/vmm_config/machine_config.rs | 4 ++-- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5759c8197d9..bc5abd81892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,13 @@ and this project adheres to ### Deprecated +- [#4948](https://github.com/firecracker-microvm/firecracker/pull/4948): + Deprecated the `page_size_kib` field in the + [UFFD handshake](docs/snapshotting/handling-page-faults-on-snapshot-resume.md#registering-memory-to-be-handled-via-userfault-file-descriptors), + and replaced it with a `page_size` field. The `page_size_kib` field is + misnamed, as the value Firecracker sets it to is actually the page size in + _bytes_, not KiB. It will be removed in Firecracker 2.0. + ### Removed ### Fixed diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index ccb4938ef01..3d4b92e0079 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -32,7 +32,7 @@ pub struct GuestRegionUffdMapping { /// Offset in the backend file/buffer where the region contents are. pub offset: u64, /// The configured page size for this memory region. - pub page_size_kib: usize, + pub page_size: usize, } impl GuestRegionUffdMapping { @@ -79,7 +79,7 @@ impl UffdHandler { mappings.len() ) }); - let page_size = first_mapping.page_size_kib; + let page_size = first_mapping.page_size; // Make sure memory size matches backing data size. assert_eq!(memsize, size); @@ -152,10 +152,7 @@ impl UffdHandler { return false; } Err(Error::CopyFailed(errno)) - if std::io::Error::from(errno).raw_os_error().unwrap() == libc::EEXIST => - { - () - } + if std::io::Error::from(errno).raw_os_error().unwrap() == libc::EEXIST => {} Err(e) => { panic!("Uffd copy failed: {e:?}"); } @@ -364,7 +361,7 @@ mod tests { base_host_virt_addr: 0, size: 0x1000, offset: 0, - page_size_kib: 4096, + page_size: 4096, }]; let dummy_memory_region_json = serde_json::to_string(&dummy_memory_region).unwrap(); @@ -397,7 +394,7 @@ mod tests { base_host_virt_addr: 0, size: 0, offset: 0, - page_size_kib: 4096, + page_size: 4096, }]; let error_memory_region_json = serde_json::to_string(&error_memory_region).unwrap(); stream diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 95616972247..9d245e64821 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -108,6 +108,11 @@ pub struct GuestRegionUffdMapping { /// Offset in the backend file/buffer where the region contents are. pub offset: u64, /// The configured page size for this memory region. + pub page_size: usize, + /// The configured page size **in bytes** for this memory region. The name is + /// wrong but cannot be changed due to being API, so this field is deprecated, + /// to be removed in 2.0. + #[deprecated] pub page_size_kib: usize, } @@ -593,11 +598,13 @@ fn create_guest_memory( let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions()); let mut offset = 0; for mem_region in guest_memory.iter() { + #[allow(deprecated)] backend_mappings.push(GuestRegionUffdMapping { base_host_virt_addr: mem_region.as_ptr() as u64, size: mem_region.size(), offset, - page_size_kib: huge_pages.page_size_kib(), + page_size: huge_pages.page_size(), + page_size_kib: huge_pages.page_size(), }); offset += mem_region.size() as u64; } @@ -788,26 +795,26 @@ mod tests { assert_eq!(uffd_regions.len(), 1); assert_eq!(uffd_regions[0].size, 0x20000); assert_eq!(uffd_regions[0].offset, 0); - assert_eq!( - uffd_regions[0].page_size_kib, - HugePageConfig::None.page_size_kib() - ); + assert_eq!(uffd_regions[0].page_size, HugePageConfig::None.page_size()); } #[test] fn test_send_uffd_handshake() { + #[allow(deprecated)] let uffd_regions = vec![ GuestRegionUffdMapping { base_host_virt_addr: 0, size: 0x100000, offset: 0, - page_size_kib: HugePageConfig::None.page_size_kib(), + page_size: HugePageConfig::None.page_size(), + page_size_kib: HugePageConfig::None.page_size(), }, GuestRegionUffdMapping { base_host_virt_addr: 0x100000, size: 0x200000, offset: 0, - page_size_kib: HugePageConfig::Hugetlbfs2M.page_size_kib(), + page_size: HugePageConfig::Hugetlbfs2M.page_size(), + page_size_kib: HugePageConfig::Hugetlbfs2M.page_size(), }, ]; diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 0a140ea890b..cfe7105fdf8 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -71,8 +71,8 @@ impl HugePageConfig { matches!(self, HugePageConfig::Hugetlbfs2M) } - /// Gets the page size in KiB of this [`HugePageConfig`]. - pub fn page_size_kib(&self) -> usize { + /// Gets the page size in bytes of this [`HugePageConfig`]. + pub fn page_size(&self) -> usize { match self { HugePageConfig::None => 4096, HugePageConfig::Hugetlbfs2M => 2 * 1024 * 1024, From fc8517044adc7121966fd38f8220ae89cd958aac Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Wed, 19 Mar 2025 16:10:52 +0100 Subject: [PATCH 400/464] fix: try to make UFFD handlers more robust According to our UFFD protocol, UFFD handlers negotiate with Firecracker during initialization and wait for it to send over a UDS the UFFD file descriptor along with the memory mappings that are being handled over the UFFD. During this handshake, our (testing only/not production grade) UFFD handlers issue what essentially is a `recvmsg` that should return with the UFFD fd and the mappings. Some times instead of the file descriptor, the `recvmsg` wrapper returns a `None` value for the file descriptor. When this happens, the UFFD handler crashes and Firecracker process hangs. According to `man recv(2)`: ``` Datagram sockets in various domains (e.g., the UNIX and Internet domains) permit zero-length datagrams. When such a datagram is received, the return value is 0. ``` which means it is possible to receive a zero-length message (we are communicating with Firecracker over a UDS). Add logic to our UFFD handlers to retry the negotiation with Firecracker up to 5 times before giving up. This helps making them (slightly) more robust. Also, we add some logging in the receive logic so that we can inspect failures post-mortem. Signed-off-by: Babis Chalios --- src/firecracker/examples/uffd/uffd_utils.rs | 50 +++++++++++++++------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index 3d4b92e0079..939a04fa23a 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -52,21 +52,45 @@ pub struct UffdHandler { } impl UffdHandler { - pub fn from_unix_stream(stream: &UnixStream, backing_buffer: *const u8, size: usize) -> Self { - let mut message_buf = vec![0u8; 1024]; - let (bytes_read, file) = stream - .recv_with_fd(&mut message_buf[..]) - .expect("Cannot read from a stream"); - message_buf.resize(bytes_read, 0); + fn get_mappings_and_file(stream: &UnixStream) -> (String, File) { + // Sometimes, reading from the stream succeeds but we don't receive any + // UFFD descriptor. We don't really have a good understanding why this is + // happening, but let's try to be a bit more robust and retry a few times + // before we declare defeat. + for _ in 1..=5 { + let mut message_buf = vec![0u8; 1024]; + let (bytes_read, file) = match stream.recv_with_fd(&mut message_buf[..]) { + Ok(res) => res, + Err(err) => { + println!("Could not receive message from stream: {err}"); + continue; + } + }; + message_buf.resize(bytes_read, 0); + + // We do not expect to receive non-UTF-8 data from Firecracker, so this is probably + // an error we can't recover from. Just immediately abort + let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| { + panic!( + "Received body is not a utf-8 valid string. Raw bytes received: \ + {message_buf:#?}" + ) + }); + let file = match file { + Some(file) => file, + None => { + println!("Did not receive Uffd from UDS. Received body: {body}"); + continue; + } + }; + return (body, file); + } - let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| { - panic!( - "Received body is not a utf-8 valid string. Raw bytes received: {message_buf:#?}" - ) - }); - let file = - file.unwrap_or_else(|| panic!("Did not receive Uffd from UDS. Received body: {body}")); + panic!("Could not get UFFD and mappings after 5 retries"); + } + pub fn from_unix_stream(stream: &UnixStream, backing_buffer: *const u8, size: usize) -> Self { + let (body, file) = Self::get_mappings_and_file(stream); let mappings = serde_json::from_str::>(&body).unwrap_or_else(|_| { panic!("Cannot deserialize memory mappings. Received body: {body}") From 4385509ceb454b12d76e209169a8a34f74e282ae Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 19 Mar 2025 12:24:47 +0000 Subject: [PATCH 401/464] chore: enable SVE and PAC custom template for G4 Enable SVE and PAC custom template for G4. Signed-off-by: Egor Lazarchuk --- tests/framework/utils_cpu_templates.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 56021a21aaa..0d8f9cd843b 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -58,6 +58,8 @@ def get_supported_custom_cpu_templates(): return ["v1n1", "aarch64_with_sve_and_pac"] case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V1: return ["aarch64_with_sve_and_pac"] + case CpuVendor.ARM, CpuModel.ARM_NEOVERSE_V2: + return ["aarch64_with_sve_and_pac"] case _: return [] From 55983220455f0fb7c65993d6e597216eeffa4df3 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 19 Mar 2025 12:26:26 +0000 Subject: [PATCH 402/464] feat(tests): test snapshot cycle restore with cpu templates Add template parameter to the snapshot cycle test to increase the test coverage. Signed-off-by: Egor Lazarchuk --- tests/integration_tests/functional/test_snapshot_basic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index cf20354bcce..067ee02e7aa 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -121,6 +121,7 @@ def test_5_snapshots( rootfs, snapshot_type, use_snapshot_editor, + cpu_template_any, ): """ Create and load 5 snapshots. @@ -136,6 +137,7 @@ def test_5_snapshots( mem_size_mib=512, track_dirty_pages=diff_snapshots, ) + vm.set_cpu_template(cpu_template_any) vm.add_net_iface() vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path=VSOCK_UDS_PATH) vm.start() From c4a9ea9001d9407ba1d6d7555eee62eba0ad50a5 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 19 Mar 2025 12:17:13 +0000 Subject: [PATCH 403/464] refactor(tests): rename test_5_snapshots and reduce the number of cycles Rename test to `test_cycled_snapshot_restore` and add a better comment to better explain what the test does. Also reduce number of cycles to 3 to speed test a bit. Signed-off-by: Egor Lazarchuk --- .../functional/test_snapshot_basic.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 067ee02e7aa..deb9b2dd6c3 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -113,7 +113,7 @@ def test_snapshot_current_version(uvm_nano): # TODO: Multiple microvm sizes must be tested in the async pipeline. @pytest.mark.parametrize("snapshot_type", [SnapshotType.DIFF, SnapshotType.FULL]) @pytest.mark.parametrize("use_snapshot_editor", [False, True]) -def test_5_snapshots( +def test_cycled_snapshot_restore( bin_vsock_path, tmp_path, microvm_factory, @@ -124,10 +124,14 @@ def test_5_snapshots( cpu_template_any, ): """ - Create and load 5 snapshots. + Run a cycle of VM restoration and VM snapshot creation where new VM is + restored from a snapshot of the previous one. """ + # This is an arbitrary selected value. It is big enough to test the + # functionality, but small enough to not be annoying long to run. + cycles = 3 + logger = logging.getLogger("snapshot_sequence") - seq_len = 5 diff_snapshots = snapshot_type == SnapshotType.DIFF vm = microvm_factory.build(guest_kernel, rootfs) @@ -155,7 +159,7 @@ def test_5_snapshots( vm.kill() for microvm in microvm_factory.build_n_from_snapshot( - snapshot, seq_len, incremental=True, use_snapshot_editor=use_snapshot_editor + snapshot, cycles, incremental=True, use_snapshot_editor=use_snapshot_editor ): # FIXME: This and the sleep below reduce the rate of vsock/ssh connection # related spurious test failures, although we do not know why this is the case. From aa73f4575102e1ddca6d37a7af8f43b08a334d6b Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Thu, 20 Mar 2025 10:36:50 +0000 Subject: [PATCH 404/464] fix(tests): adjust G4 guest features with sve+pac cpu template Add a case for G4 with sve+pac template to the guest cpu feature check test. Signed-off-by: Egor Lazarchuk --- .../functional/test_cpu_features_aarch64.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py index 5b667d0b34d..ab59f79c706 100644 --- a/tests/integration_tests/functional/test_cpu_features_aarch64.py +++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py @@ -26,6 +26,10 @@ G4_FEATS = (G3_FEATS | set("bti flagm2 frint sb".split())) - set("sm3 sm4".split()) +G4_SVE_AND_PAC = set( + "paca pacg sve sve2 sveaes svebitperm svepmull svesha3 svebf16 svei8mm".split() +) + def test_guest_cpu_features(uvm_any): """Check the CPU features for a microvm with different CPU templates""" @@ -47,6 +51,8 @@ def test_guest_cpu_features(uvm_any): expected_cpu_features = G3_FEATS case CpuModel.ARM_NEOVERSE_V2, None: expected_cpu_features = G4_FEATS + case CpuModel.ARM_NEOVERSE_V2, "aarch64_with_sve_and_pac": + expected_cpu_features = G4_FEATS | G4_SVE_AND_PAC guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split()) assert guest_feats == expected_cpu_features From 69522c8ef0e5918d7803ae12e54f3839190768e2 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Fri, 21 Mar 2025 12:26:21 +0100 Subject: [PATCH 405/464] fix: sleep between retries during UFFD handler negotiation During fc8517044adc, we changed the UFFD handler logic to retry the negotiation with Firecracker up to 5 times in case of failures. Retries happen immediately. Add a small timeout between retries to make this even more robust. Signed-off-by: Babis Chalios --- src/firecracker/examples/uffd/uffd_utils.rs | 52 +++++++++++---------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/firecracker/examples/uffd/uffd_utils.rs b/src/firecracker/examples/uffd/uffd_utils.rs index 939a04fa23a..07ed48f9439 100644 --- a/src/firecracker/examples/uffd/uffd_utils.rs +++ b/src/firecracker/examples/uffd/uffd_utils.rs @@ -10,6 +10,7 @@ use std::fs::File; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; use std::os::unix::net::UnixStream; use std::ptr; +use std::time::Duration; use serde::{Deserialize, Serialize}; use userfaultfd::{Error, Event, Uffd}; @@ -52,38 +53,41 @@ pub struct UffdHandler { } impl UffdHandler { + fn try_get_mappings_and_file( + stream: &UnixStream, + ) -> Result<(String, Option), std::io::Error> { + let mut message_buf = vec![0u8; 1024]; + let (bytes_read, file) = stream.recv_with_fd(&mut message_buf[..])?; + message_buf.resize(bytes_read, 0); + + // We do not expect to receive non-UTF-8 data from Firecracker, so this is probably + // an error we can't recover from. Just immediately abort + let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| { + panic!( + "Received body is not a utf-8 valid string. Raw bytes received: {message_buf:#?}" + ) + }); + Ok((body, file)) + } + fn get_mappings_and_file(stream: &UnixStream) -> (String, File) { // Sometimes, reading from the stream succeeds but we don't receive any // UFFD descriptor. We don't really have a good understanding why this is // happening, but let's try to be a bit more robust and retry a few times // before we declare defeat. for _ in 1..=5 { - let mut message_buf = vec![0u8; 1024]; - let (bytes_read, file) = match stream.recv_with_fd(&mut message_buf[..]) { - Ok(res) => res, - Err(err) => { - println!("Could not receive message from stream: {err}"); - continue; + match Self::try_get_mappings_and_file(stream) { + Ok((body, Some(file))) => { + return (body, file); } - }; - message_buf.resize(bytes_read, 0); - - // We do not expect to receive non-UTF-8 data from Firecracker, so this is probably - // an error we can't recover from. Just immediately abort - let body = String::from_utf8(message_buf.clone()).unwrap_or_else(|_| { - panic!( - "Received body is not a utf-8 valid string. Raw bytes received: \ - {message_buf:#?}" - ) - }); - let file = match file { - Some(file) => file, - None => { - println!("Did not receive Uffd from UDS. Received body: {body}"); - continue; + Ok((body, None)) => { + println!("Didn't receive UFFD over socket. We received: '{body}'. Retrying..."); } - }; - return (body, file); + Err(err) => { + println!("Could not get UFFD and mapping from Firecracker: {err}. Retrying..."); + } + } + std::thread::sleep(Duration::from_millis(100)); } panic!("Could not get UFFD and mappings after 5 retries"); From fc55a48b17657e7b1ae8626b76f8240a0a858cb5 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Fri, 21 Mar 2025 12:09:49 +0100 Subject: [PATCH 406/464] test: increase cases for test_population_latency Gathering more data should make the A/B test more stable and avoid intermittent failures. Signed-off-by: Babis Chalios --- .../performance/test_snapshot_ab.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/integration_tests/performance/test_snapshot_ab.py b/tests/integration_tests/performance/test_snapshot_ab.py index 6dc2d045a45..b4f1b8f15dc 100644 --- a/tests/integration_tests/performance/test_snapshot_ab.py +++ b/tests/integration_tests/performance/test_snapshot_ab.py @@ -142,7 +142,12 @@ def test_restore_latency( @pytest.mark.parametrize("uffd_handler", [None, "on_demand", "fault_all"]) @pytest.mark.parametrize("huge_pages", HugePagesConfig) def test_post_restore_latency( - microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, uffd_handler, huge_pages + microvm_factory, + rootfs, + guest_kernel_linux_5_10, + metrics, + uffd_handler, + huge_pages, ): """Collects latency metric of post-restore memory accesses done inside the guest""" if huge_pages != HugePagesConfig.NONE and uffd_handler is None: @@ -190,11 +195,20 @@ def test_post_restore_latency( @pytest.mark.nonci @pytest.mark.parametrize("huge_pages", HugePagesConfig) +@pytest.mark.parametrize( + ("vcpus", "mem"), [(1, 128), (1, 1024), (2, 2048), (3, 4096), (4, 6144)] +) def test_population_latency( - microvm_factory, rootfs, guest_kernel_linux_5_10, metrics, huge_pages + microvm_factory, + rootfs, + guest_kernel_linux_5_10, + metrics, + huge_pages, + vcpus, + mem, ): """Collects population latency metrics (e.g. how long it takes UFFD handler to fault in all memory)""" - test_setup = SnapshotRestoreTest(mem=128, vcpus=1, huge_pages=huge_pages) + test_setup = SnapshotRestoreTest(mem=mem, vcpus=vcpus, huge_pages=huge_pages) vm = test_setup.boot_vm(microvm_factory, guest_kernel_linux_5_10, rootfs) metrics.set_dimensions( From 83a9a55abd48586e9774cf59dbcc284057877c67 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Fri, 21 Mar 2025 15:06:56 +0100 Subject: [PATCH 407/464] doc: clarify kernel configuration usage in our repo We keep in the repo the kernel configurations from which we build the kernel images we use in our CI pipelines. However, we don't mention what kernel sources we use to build these kernel images. Clarify in the documentation that these configurations are meant to be used with kernels provided by Amazon Linux and that we don't guarantee that they can be used to build kernels from upstream Linux. Signed-off-by: Babis Chalios --- docs/kernel-policy.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/kernel-policy.md b/docs/kernel-policy.md index d609116054e..5f079f0d04b 100644 --- a/docs/kernel-policy.md +++ b/docs/kernel-policy.md @@ -37,6 +37,19 @@ The guest kernel configs used in our validation pipelines can be found [here](../resources/guest_configs/) while a breakdown of the relevant guest kernel modules can be found in the next section. +We use these configurations to build microVM-specific kernels vended by Amazon +Linux. microVM kernel source code is published in the Amazon Linux +[linux repo](https://github.com/amazonlinux/linux) under tags in the form of +`microvm-kernel-*`, e.g. 6.1.128-3.201.amazn2023 kernel can be found +[here](https://github.com/amazonlinux/linux/tree/microvm-kernel-6.1.128-3.201.amzn2023). +These kernels may have diverged from the equivalent mainline versions, as we +often backport patches that we require for supporting Firecracker features not +present in the kernel versions we officially support. As a result, kernel +configurations found in this repo should be used to build exclusively the +aforementioned Amazon Linux kernels. We do not guarantee that using these +configurations to build upstream kernels, will work or produce usable kernel +images. + ## Guest kernel configuration items The configuration items that may be relevant for Firecracker are: From 0ee10bb8c065669b4b7642fa8cf80a25e612ae07 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Thu, 20 Mar 2025 10:50:37 +0100 Subject: [PATCH 408/464] refactor: move arch specific KVM code into modules Follow up of the refactoring we did in the past around vstate/vm.rs, where we separate architecture specific code in modules, keeping only the arch-independent code in 'kvm/mod.rs'. No functional changes intended. Signed-off-by: Babis Chalios --- src/vmm/src/vstate/kvm/aarch64.rs | 66 ++++++++++++ src/vmm/src/vstate/{kvm.rs => kvm/mod.rs} | 117 +++------------------- src/vmm/src/vstate/kvm/x86_64.rs | 74 ++++++++++++++ 3 files changed, 153 insertions(+), 104 deletions(-) create mode 100644 src/vmm/src/vstate/kvm/aarch64.rs rename src/vmm/src/vstate/{kvm.rs => kvm/mod.rs} (57%) create mode 100644 src/vmm/src/vstate/kvm/x86_64.rs diff --git a/src/vmm/src/vstate/kvm/aarch64.rs b/src/vmm/src/vstate/kvm/aarch64.rs new file mode 100644 index 00000000000..de54848c7b8 --- /dev/null +++ b/src/vmm/src/vstate/kvm/aarch64.rs @@ -0,0 +1,66 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::convert::Infallible; + +use kvm_ioctls::Kvm as KvmFd; + +use crate::cpu_config::templates::KvmCapability; + +/// ['Kvm'] initialization can't fail for Aarch64 +pub type KvmArchError = Infallible; + +/// Errors associated with the wrappers over KVM ioctls. +/// Needs `rustfmt::skip` to make multiline comments work +/// Optional capabilities. +#[derive(Debug, Default)] +pub struct OptionalCapabilities { + /// KVM_CAP_COUNTER_OFFSET + pub counter_offset: bool, +} + +/// Struct with kvm fd and kvm associated parameters. +#[derive(Debug)] +pub struct Kvm { + /// KVM fd. + pub fd: KvmFd, + /// Maximum number of memory slots allowed by KVM. + pub max_memslots: usize, + /// Additional capabilities that were specified in cpu template. + pub kvm_cap_modifiers: Vec, +} + +impl Kvm { + pub(crate) const DEFAULT_CAPABILITIES: [u32; 7] = [ + kvm_bindings::KVM_CAP_IOEVENTFD, + kvm_bindings::KVM_CAP_IRQFD, + kvm_bindings::KVM_CAP_USER_MEMORY, + kvm_bindings::KVM_CAP_ARM_PSCI_0_2, + kvm_bindings::KVM_CAP_DEVICE_CTRL, + kvm_bindings::KVM_CAP_MP_STATE, + kvm_bindings::KVM_CAP_ONE_REG, + ]; + + /// Initialize [`Kvm`] type for Aarch64 architecture + pub fn init_arch( + fd: KvmFd, + max_memslots: usize, + kvm_cap_modifiers: Vec, + ) -> Result { + Ok(Self { + fd, + max_memslots, + kvm_cap_modifiers, + }) + } + + /// Returns struct with optional capabilities statuses. + pub fn optional_capabilities(&self) -> OptionalCapabilities { + OptionalCapabilities { + counter_offset: self + .fd + .check_extension_raw(kvm_bindings::KVM_CAP_COUNTER_OFFSET.into()) + != 0, + } + } +} diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm/mod.rs similarity index 57% rename from src/vmm/src/vstate/kvm.rs rename to src/vmm/src/vstate/kvm/mod.rs index 7c44cfb91cb..6b0978d24c9 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm/mod.rs @@ -2,16 +2,22 @@ // SPDX-License-Identifier: Apache-2.0 use kvm_bindings::KVM_API_VERSION; -#[cfg(target_arch = "x86_64")] -use kvm_bindings::{CpuId, KVM_MAX_CPUID_ENTRIES, MsrList}; use kvm_ioctls::Kvm as KvmFd; use serde::{Deserialize, Serialize}; -#[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::xstate::{XstateError, request_dynamic_xstate_features}; use crate::cpu_config::templates::KvmCapability; use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; +#[cfg(target_arch = "aarch64")] +mod aarch64; +#[cfg(target_arch = "x86_64")] +mod x86_64; + +#[cfg(target_arch = "aarch64")] +pub use aarch64::{Kvm, KvmArchError, OptionalCapabilities}; +#[cfg(target_arch = "x86_64")] +pub use x86_64::{Kvm, KvmArchError}; + /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work #[rustfmt::skip] @@ -24,29 +30,10 @@ pub enum KvmError { /** Error creating KVM object: {0} Make sure the user launching the firecracker process is \ configured on the /dev/kvm file's ACL. */ Kvm(kvm_ioctls::Error), - #[cfg(target_arch = "x86_64")] - /// Failed to get supported cpuid: {0} - GetSupportedCpuId(kvm_ioctls::Error), /// The number of configured slots is bigger than the maximum reported by KVM NotEnoughMemorySlots, - #[cfg(target_arch = "x86_64")] - /// Failed to request permission for dynamic XSTATE features: {0} - XstateFeatures(XstateError), -} - -/// Struct with kvm fd and kvm associated paramenters. -#[derive(Debug)] -pub struct Kvm { - /// KVM fd. - pub fd: KvmFd, - /// Maximum number of memory slots allowed by KVM. - pub max_memslots: usize, - /// Additional capabilities that were specified in cpu template. - pub kvm_cap_modifiers: Vec, - - #[cfg(target_arch = "x86_64")] - /// Supported CpuIds. - pub supported_cpuid: CpuId, + /// Architecture specific error: {0} + ArchError(#[from] KvmArchError) } impl Kvm { @@ -67,36 +54,7 @@ impl Kvm { let max_memslots = kvm_fd.get_nr_memslots(); - #[cfg(target_arch = "aarch64")] - { - Ok(Self { - fd: kvm_fd, - max_memslots, - kvm_cap_modifiers, - }) - } - - #[cfg(target_arch = "x86_64")] - { - request_dynamic_xstate_features().map_err(KvmError::XstateFeatures)?; - - let supported_cpuid = kvm_fd - .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) - .map_err(KvmError::GetSupportedCpuId)?; - - Ok(Kvm { - fd: kvm_fd, - max_memslots, - kvm_cap_modifiers, - supported_cpuid, - }) - } - } - - /// Msrs needed to be saved on snapshot creation. - #[cfg(target_arch = "x86_64")] - pub fn msrs_to_save(&self) -> Result { - crate::arch::x86_64::msr::get_msrs_to_save(&self.fd) + Ok(Kvm::init_arch(kvm_fd, max_memslots, kvm_cap_modifiers)?) } /// Check guest memory does not have more regions than kvm allows. @@ -144,55 +102,6 @@ impl Kvm { } } } -#[cfg(target_arch = "aarch64")] -/// Optional capabilities. -#[derive(Debug, Default)] -pub struct OptionalCapabilities { - /// KVM_CAP_COUNTER_OFFSET - pub counter_offset: bool, -} -#[cfg(target_arch = "aarch64")] -impl Kvm { - const DEFAULT_CAPABILITIES: [u32; 7] = [ - kvm_bindings::KVM_CAP_IOEVENTFD, - kvm_bindings::KVM_CAP_IRQFD, - kvm_bindings::KVM_CAP_USER_MEMORY, - kvm_bindings::KVM_CAP_ARM_PSCI_0_2, - kvm_bindings::KVM_CAP_DEVICE_CTRL, - kvm_bindings::KVM_CAP_MP_STATE, - kvm_bindings::KVM_CAP_ONE_REG, - ]; - - /// Returns struct with optional capabilities statuses. - pub fn optional_capabilities(&self) -> OptionalCapabilities { - OptionalCapabilities { - counter_offset: self - .fd - .check_extension_raw(kvm_bindings::KVM_CAP_COUNTER_OFFSET.into()) - != 0, - } - } -} - -#[cfg(target_arch = "x86_64")] -impl Kvm { - const DEFAULT_CAPABILITIES: [u32; 14] = [ - kvm_bindings::KVM_CAP_IRQCHIP, - kvm_bindings::KVM_CAP_IOEVENTFD, - kvm_bindings::KVM_CAP_IRQFD, - kvm_bindings::KVM_CAP_USER_MEMORY, - kvm_bindings::KVM_CAP_SET_TSS_ADDR, - kvm_bindings::KVM_CAP_PIT2, - kvm_bindings::KVM_CAP_PIT_STATE2, - kvm_bindings::KVM_CAP_ADJUST_CLOCK, - kvm_bindings::KVM_CAP_DEBUGREGS, - kvm_bindings::KVM_CAP_MP_STATE, - kvm_bindings::KVM_CAP_VCPU_EVENTS, - kvm_bindings::KVM_CAP_XCRS, - kvm_bindings::KVM_CAP_XSAVE, - kvm_bindings::KVM_CAP_EXT_CPUID, - ]; -} /// Structure holding an general specific VM state. #[derive(Debug, Default, Serialize, Deserialize)] diff --git a/src/vmm/src/vstate/kvm/x86_64.rs b/src/vmm/src/vstate/kvm/x86_64.rs new file mode 100644 index 00000000000..4d77b0fdbb6 --- /dev/null +++ b/src/vmm/src/vstate/kvm/x86_64.rs @@ -0,0 +1,74 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use kvm_bindings::{CpuId, KVM_MAX_CPUID_ENTRIES, MsrList}; +use kvm_ioctls::Kvm as KvmFd; + +use crate::arch::x86_64::xstate::{XstateError, request_dynamic_xstate_features}; +use crate::cpu_config::templates::KvmCapability; + +/// Architecture specific error for KVM initialization +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum KvmArchError { + /// Failed to get supported cpuid: {0} + GetSupportedCpuId(kvm_ioctls::Error), + /// Failed to request permission for dynamic XSTATE features: {0} + XstateFeatures(XstateError), +} + +/// Struct with kvm fd and kvm associated parameters. +#[derive(Debug)] +pub struct Kvm { + /// KVM fd. + pub fd: KvmFd, + /// Maximum number of memory slots allowed by KVM. + pub max_memslots: usize, + /// Additional capabilities that were specified in cpu template. + pub kvm_cap_modifiers: Vec, + /// Supported CpuIds. + pub supported_cpuid: CpuId, +} + +impl Kvm { + pub(crate) const DEFAULT_CAPABILITIES: [u32; 14] = [ + kvm_bindings::KVM_CAP_IRQCHIP, + kvm_bindings::KVM_CAP_IOEVENTFD, + kvm_bindings::KVM_CAP_IRQFD, + kvm_bindings::KVM_CAP_USER_MEMORY, + kvm_bindings::KVM_CAP_SET_TSS_ADDR, + kvm_bindings::KVM_CAP_PIT2, + kvm_bindings::KVM_CAP_PIT_STATE2, + kvm_bindings::KVM_CAP_ADJUST_CLOCK, + kvm_bindings::KVM_CAP_DEBUGREGS, + kvm_bindings::KVM_CAP_MP_STATE, + kvm_bindings::KVM_CAP_VCPU_EVENTS, + kvm_bindings::KVM_CAP_XCRS, + kvm_bindings::KVM_CAP_XSAVE, + kvm_bindings::KVM_CAP_EXT_CPUID, + ]; + + /// Initialize [`Kvm`] type for x86_64 architecture + pub fn init_arch( + fd: KvmFd, + max_memslots: usize, + kvm_cap_modifiers: Vec, + ) -> Result { + request_dynamic_xstate_features().map_err(KvmArchError::XstateFeatures)?; + + let supported_cpuid = fd + .get_supported_cpuid(KVM_MAX_CPUID_ENTRIES) + .map_err(KvmArchError::GetSupportedCpuId)?; + + Ok(Kvm { + fd, + max_memslots, + kvm_cap_modifiers, + supported_cpuid, + }) + } + + /// Msrs needed to be saved on snapshot creation. + pub fn msrs_to_save(&self) -> Result { + crate::arch::x86_64::msr::get_msrs_to_save(&self.fd) + } +} From 56c573ad324120fcf8e960c6a18d105dca14451c Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Mon, 24 Mar 2025 12:57:17 +0100 Subject: [PATCH 409/464] chore: move KVM architecture-specific state in vmm::arch module Move KVM architecture-specific code under the `vmm::arch` module, so that we start having all architecture-specific code under a single module. Signed-off-by: Babis Chalios --- src/vmm/src/arch/aarch64/mod.rs | 2 ++ .../kvm/aarch64.rs => arch/aarch64/vstate/kvm.rs} | 0 src/vmm/src/arch/aarch64/vstate/mod.rs | 5 +++++ src/vmm/src/arch/mod.rs | 4 ++++ src/vmm/src/arch/x86_64/mod.rs | 4 +++- .../kvm/x86_64.rs => arch/x86_64/vstate/kvm.rs} | 0 src/vmm/src/arch/x86_64/vstate/mod.rs | 5 +++++ src/vmm/src/vstate/{kvm/mod.rs => kvm.rs} | 11 +---------- 8 files changed, 20 insertions(+), 11 deletions(-) rename src/vmm/src/{vstate/kvm/aarch64.rs => arch/aarch64/vstate/kvm.rs} (100%) create mode 100644 src/vmm/src/arch/aarch64/vstate/mod.rs rename src/vmm/src/{vstate/kvm/x86_64.rs => arch/x86_64/vstate/kvm.rs} (100%) create mode 100644 src/vmm/src/arch/x86_64/vstate/mod.rs rename src/vmm/src/vstate/{kvm/mod.rs => kvm.rs} (94%) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index a409f330c56..650595df070 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -11,6 +11,8 @@ pub mod layout; pub mod regs; /// Helper methods for VcpuFd. pub mod vcpu; +/// Architecture specific microVM state. +pub mod vstate; use std::cmp::min; use std::collections::HashMap; diff --git a/src/vmm/src/vstate/kvm/aarch64.rs b/src/vmm/src/arch/aarch64/vstate/kvm.rs similarity index 100% rename from src/vmm/src/vstate/kvm/aarch64.rs rename to src/vmm/src/arch/aarch64/vstate/kvm.rs diff --git a/src/vmm/src/arch/aarch64/vstate/mod.rs b/src/vmm/src/arch/aarch64/vstate/mod.rs new file mode 100644 index 00000000000..c544a04628a --- /dev/null +++ b/src/vmm/src/arch/aarch64/vstate/mod.rs @@ -0,0 +1,5 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// Architecture specific KVM-related code +pub mod kvm; diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 41530737089..107729bbb1b 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -12,6 +12,8 @@ use vm_memory::GuestAddress; #[cfg(target_arch = "aarch64")] pub mod aarch64; +#[cfg(target_arch = "aarch64")] +pub use aarch64::vstate::kvm::{Kvm, KvmArchError, OptionalCapabilities}; #[cfg(target_arch = "aarch64")] pub use aarch64::{ ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, @@ -30,6 +32,8 @@ pub use crate::arch::x86_64::{ layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, }; +#[cfg(target_arch = "x86_64")] +pub use x86_64::vstate::kvm::{Kvm, KvmArchError}; /// Types of devices that can get attached to this platform. #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)] diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index f10fd3446d8..c01c8cd79e4 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -19,6 +19,8 @@ mod mptable; pub mod msr; /// Logic for configuring x86_64 registers. pub mod regs; +/// Architecture specific microVM state. +pub mod vstate; /// Logic for configuring XSTATE features. pub mod xstate; @@ -221,7 +223,7 @@ fn configure_pvh( // boot_params. This will be stored at PVH_INFO_START address, and %rbx // will be initialized to contain PVH_INFO_START prior to starting the // guest, as required by the PVH ABI. - #[allow(clippy::cast_possible_truncation)] // the vec lenghts are single digit integers + #[allow(clippy::cast_possible_truncation)] // the vec lengths are single digit integers let mut start_info = hvm_start_info { magic: XEN_HVM_START_MAGIC_VALUE, version: 1, diff --git a/src/vmm/src/vstate/kvm/x86_64.rs b/src/vmm/src/arch/x86_64/vstate/kvm.rs similarity index 100% rename from src/vmm/src/vstate/kvm/x86_64.rs rename to src/vmm/src/arch/x86_64/vstate/kvm.rs diff --git a/src/vmm/src/arch/x86_64/vstate/mod.rs b/src/vmm/src/arch/x86_64/vstate/mod.rs new file mode 100644 index 00000000000..c544a04628a --- /dev/null +++ b/src/vmm/src/arch/x86_64/vstate/mod.rs @@ -0,0 +1,5 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// Architecture specific KVM-related code +pub mod kvm; diff --git a/src/vmm/src/vstate/kvm/mod.rs b/src/vmm/src/vstate/kvm.rs similarity index 94% rename from src/vmm/src/vstate/kvm/mod.rs rename to src/vmm/src/vstate/kvm.rs index 6b0978d24c9..b89d0e1a0d8 100644 --- a/src/vmm/src/vstate/kvm/mod.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -5,19 +5,10 @@ use kvm_bindings::KVM_API_VERSION; use kvm_ioctls::Kvm as KvmFd; use serde::{Deserialize, Serialize}; +pub use crate::arch::{Kvm, KvmArchError}; use crate::cpu_config::templates::KvmCapability; use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; -#[cfg(target_arch = "aarch64")] -mod aarch64; -#[cfg(target_arch = "x86_64")] -mod x86_64; - -#[cfg(target_arch = "aarch64")] -pub use aarch64::{Kvm, KvmArchError, OptionalCapabilities}; -#[cfg(target_arch = "x86_64")] -pub use x86_64::{Kvm, KvmArchError}; - /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work #[rustfmt::skip] From 0f3e8b391512061fae21cd85245213d455cdec90 Mon Sep 17 00:00:00 2001 From: Babis Chalios Date: Mon, 24 Mar 2025 13:35:49 +0100 Subject: [PATCH 410/464] chore: move `vmm::vstate` code under `vmm::arch` Move the rest of vstate architecture-specific code under `vmm::arch`. Signed-off-by: Babis Chalios --- src/snapshot-editor/src/edit_vmstate.rs | 4 +- src/vmm/src/arch/aarch64/{vstate => }/kvm.rs | 2 - src/vmm/src/arch/aarch64/mod.rs | 8 +- src/vmm/src/arch/aarch64/vcpu.rs | 548 ++++++++++++++++-- .../vm/aarch64.rs => arch/aarch64/vm.rs} | 11 +- src/vmm/src/arch/aarch64/vstate/mod.rs | 5 - src/vmm/src/arch/mod.rs | 18 +- src/vmm/src/arch/x86_64/{vstate => }/kvm.rs | 0 src/vmm/src/arch/x86_64/mod.rs | 8 +- .../vcpu/x86_64.rs => arch/x86_64/vcpu.rs} | 18 +- .../vm/x86_64.rs => arch/x86_64/vm.rs} | 9 +- src/vmm/src/arch/x86_64/vstate/mod.rs | 5 - src/vmm/src/builder.rs | 4 +- src/vmm/src/cpu_config/aarch64/mod.rs | 4 +- src/vmm/src/gdb/target.rs | 2 +- src/vmm/src/vstate/{vcpu/mod.rs => vcpu.rs} | 13 +- src/vmm/src/vstate/vcpu/aarch64.rs | 499 ---------------- src/vmm/src/vstate/{vm/mod.rs => vm.rs} | 18 +- 18 files changed, 571 insertions(+), 605 deletions(-) rename src/vmm/src/arch/aarch64/{vstate => }/kvm.rs (94%) rename src/vmm/src/{vstate/vm/aarch64.rs => arch/aarch64/vm.rs} (90%) delete mode 100644 src/vmm/src/arch/aarch64/vstate/mod.rs rename src/vmm/src/arch/x86_64/{vstate => }/kvm.rs (100%) rename src/vmm/src/{vstate/vcpu/x86_64.rs => arch/x86_64/vcpu.rs} (99%) rename src/vmm/src/{vstate/vm/x86_64.rs => arch/x86_64/vm.rs} (97%) delete mode 100644 src/vmm/src/arch/x86_64/vstate/mod.rs rename src/vmm/src/vstate/{vcpu/mod.rs => vcpu.rs} (99%) delete mode 100644 src/vmm/src/vstate/vcpu/aarch64.rs rename src/vmm/src/vstate/{vm/mod.rs => vm.rs} (95%) diff --git a/src/snapshot-editor/src/edit_vmstate.rs b/src/snapshot-editor/src/edit_vmstate.rs index a96f84db6a0..ba5b8370096 100644 --- a/src/snapshot-editor/src/edit_vmstate.rs +++ b/src/snapshot-editor/src/edit_vmstate.rs @@ -99,7 +99,7 @@ mod tests { const KVM_REG_SIZE_U32: u64 = 0x20000000000000; use vmm::arch::aarch64::regs::Aarch64RegisterRef; - use vmm::vstate::vcpu::aarch64::VcpuState; + use vmm::arch::aarch64::vcpu::VcpuState; let vcpu_state = VcpuState { regs: { @@ -158,7 +158,7 @@ mod tests { const KVM_REG_SIZE_U32: u64 = 0x20000000000000; use vmm::arch::aarch64::regs::Aarch64RegisterRef; - use vmm::vstate::vcpu::aarch64::VcpuState; + use vmm::arch::aarch64::vcpu::VcpuState; let vcpu_state = VcpuState { regs: { diff --git a/src/vmm/src/arch/aarch64/vstate/kvm.rs b/src/vmm/src/arch/aarch64/kvm.rs similarity index 94% rename from src/vmm/src/arch/aarch64/vstate/kvm.rs rename to src/vmm/src/arch/aarch64/kvm.rs index de54848c7b8..12720f5066f 100644 --- a/src/vmm/src/arch/aarch64/vstate/kvm.rs +++ b/src/vmm/src/arch/aarch64/kvm.rs @@ -10,8 +10,6 @@ use crate::cpu_config::templates::KvmCapability; /// ['Kvm'] initialization can't fail for Aarch64 pub type KvmArchError = Infallible; -/// Errors associated with the wrappers over KVM ioctls. -/// Needs `rustfmt::skip` to make multiline comments work /// Optional capabilities. #[derive(Debug, Default)] pub struct OptionalCapabilities { diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 650595df070..7ab1685cf69 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -5,14 +5,16 @@ pub(crate) mod cache_info; mod fdt; /// Module for the global interrupt controller configuration. pub mod gic; +/// Architecture specific KVM-related code +pub mod kvm; /// Layout for this aarch64 system. pub mod layout; /// Logic for configuring aarch64 registers. pub mod regs; -/// Helper methods for VcpuFd. +/// Architecture specific vCPU code pub mod vcpu; -/// Architecture specific microVM state. -pub mod vstate; +/// Architecture specific VM state code +pub mod vm; use std::cmp::min; use std::collections::HashMap; diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index d46b9b56720..a126ab1a3a5 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -5,20 +5,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. +use std::fmt::{Debug, Write}; use std::mem::offset_of; use std::path::PathBuf; use kvm_bindings::*; -use kvm_ioctls::VcpuFd; +use kvm_ioctls::{VcpuExit, VcpuFd, VmFd}; +use serde::{Deserialize, Serialize}; use super::get_fdt_addr; use super::regs::*; -use crate::vstate::kvm::OptionalCapabilities; -use crate::vstate::memory::GuestMemoryMmap; +use crate::arch::EntryPoint; +use crate::arch::aarch64::kvm::OptionalCapabilities; +use crate::arch::aarch64::regs::{Aarch64RegisterVec, KVM_REG_ARM64_SVE_VLS}; +use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; +use crate::cpu_config::templates::CpuConfiguration; +use crate::logger::{IncMetric, METRICS, error}; +use crate::vcpu::{VcpuConfig, VcpuError}; +use crate::vstate::memory::{Address, GuestMemoryMmap}; +use crate::vstate::vcpu::VcpuEmulation; +use crate::vstate::vm::Vm; /// Errors thrown while setting aarch64 registers. #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] -pub enum VcpuError { +pub enum VcpuArchError { /// Failed to get register {0}: {1} GetOneReg(u64, kvm_ioctls::Error), /// Failed to set register {0}: {1} @@ -41,11 +51,11 @@ pub enum VcpuError { /// # Arguments /// /// * `regs` - reference [`Aarch64RegisterVec`] structure with all registers of a VCPU. -pub fn get_manufacturer_id_from_state(regs: &Aarch64RegisterVec) -> Result { +pub fn get_manufacturer_id_from_state(regs: &Aarch64RegisterVec) -> Result { let midr_el1 = regs.iter().find(|reg| reg.id == MIDR_EL1); match midr_el1 { Some(register) => Ok(((register.value::() >> 24) & 0xFF) as u32), - None => Err(VcpuError::GetMidrEl1( + None => Err(VcpuArchError::GetMidrEl1( "Failed to find MIDR_EL1 in vCPU state!".to_string(), )), } @@ -53,16 +63,17 @@ pub fn get_manufacturer_id_from_state(regs: &Aarch64RegisterVec) -> Result Result { +pub fn get_manufacturer_id_from_host() -> Result { let midr_el1_path = &PathBuf::from("/sys/devices/system/cpu/cpu0/regs/identification/midr_el1".to_string()); let midr_el1 = std::fs::read_to_string(midr_el1_path).map_err(|err| { - VcpuError::GetMidrEl1(format!("Failed to get MIDR_EL1 from host path: {err}")) + VcpuArchError::GetMidrEl1(format!("Failed to get MIDR_EL1 from host path: {err}")) })?; let midr_el1_trimmed = midr_el1.trim_end().trim_start_matches("0x"); - let manufacturer_id = u32::from_str_radix(midr_el1_trimmed, 16) - .map_err(|err| VcpuError::GetMidrEl1(format!("Invalid MIDR_EL1 found on host: {err}",)))?; + let manufacturer_id = u32::from_str_radix(midr_el1_trimmed, 16).map_err(|err| { + VcpuArchError::GetMidrEl1(format!("Invalid MIDR_EL1 found on host: {err}",)) + })?; Ok(manufacturer_id >> 24) } @@ -80,7 +91,7 @@ pub fn setup_boot_regs( boot_ip: u64, mem: &GuestMemoryMmap, optional_capabilities: &OptionalCapabilities, -) -> Result<(), VcpuError> { +) -> Result<(), VcpuArchError> { let kreg_off = offset_of!(kvm_regs, regs); // Get the register index of the PSTATE (Processor State) register. @@ -88,7 +99,7 @@ pub fn setup_boot_regs( let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate); vcpufd .set_one_reg(id, &PSTATE_FAULT_BITS_64.to_le_bytes()) - .map_err(|err| VcpuError::SetOneReg(id, err))?; + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; // Other vCPUs are powered off initially awaiting PSCI wakeup. if cpu_id == 0 { @@ -97,7 +108,7 @@ pub fn setup_boot_regs( let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pc); vcpufd .set_one_reg(id, &boot_ip.to_le_bytes()) - .map_err(|err| VcpuError::SetOneReg(id, err))?; + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; // Last mandatory thing to set -> the address pointing to the FDT (also called DTB). // "The device tree blob (dtb) must be placed on an 8-byte boundary and must @@ -107,7 +118,7 @@ pub fn setup_boot_regs( let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0); vcpufd .set_one_reg(id, &get_fdt_addr(mem).to_le_bytes()) - .map_err(|err| VcpuError::SetOneReg(id, err))?; + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; // Reset the physical counter for the guest. This way we avoid guest reading // host physical counter. @@ -123,18 +134,18 @@ pub fn setup_boot_regs( if optional_capabilities.counter_offset { vcpufd .set_one_reg(KVM_REG_ARM_PTIMER_CNT, &[0; 8]) - .map_err(|err| VcpuError::SetOneReg(id, err))?; + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; } } Ok(()) } /// Read the MPIDR - Multiprocessor Affinity Register. -pub fn get_mpidr(vcpufd: &VcpuFd) -> Result { +pub fn get_mpidr(vcpufd: &VcpuFd) -> Result { // MPIDR register is 64 bit wide on aarch64 let mut mpidr = [0_u8; 8]; match vcpufd.get_one_reg(MPIDR_EL1, &mut mpidr) { - Err(err) => Err(VcpuError::GetOneReg(MPIDR_EL1, err)), + Err(err) => Err(VcpuArchError::GetOneReg(MPIDR_EL1, err)), Ok(_) => Ok(u64::from_le_bytes(mpidr)), } } @@ -144,7 +155,10 @@ pub fn get_mpidr(vcpufd: &VcpuFd) -> Result { /// # Arguments /// /// * `regs` - Input/Output vector of registers. -pub fn get_all_registers(vcpufd: &VcpuFd, state: &mut Aarch64RegisterVec) -> Result<(), VcpuError> { +pub fn get_all_registers( + vcpufd: &VcpuFd, + state: &mut Aarch64RegisterVec, +) -> Result<(), VcpuArchError> { get_registers(vcpufd, &get_all_registers_ids(vcpufd)?, state) } @@ -158,12 +172,12 @@ pub fn get_registers( vcpufd: &VcpuFd, ids: &[u64], regs: &mut Aarch64RegisterVec, -) -> Result<(), VcpuError> { +) -> Result<(), VcpuArchError> { let mut big_reg = [0_u8; 256]; for id in ids.iter() { let reg_size = vcpufd .get_one_reg(*id, &mut big_reg) - .map_err(|e| VcpuError::GetOneReg(*id, e))?; + .map_err(|e| VcpuArchError::GetOneReg(*id, e))?; let reg_ref = Aarch64RegisterRef::new(*id, &big_reg[0..reg_size]); regs.push(reg_ref); } @@ -171,10 +185,10 @@ pub fn get_registers( } /// Returns all registers ids, including core and system -pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result, VcpuError> { +pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result, VcpuArchError> { // Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are // less than 500 registers expected, resize to the reported size when necessary. - let mut reg_list = RegList::new(500).map_err(VcpuError::Fam)?; + let mut reg_list = RegList::new(500).map_err(VcpuArchError::Fam)?; match vcpufd.get_reg_list(&mut reg_list) { Ok(_) => Ok(reg_list.as_slice().to_vec()), @@ -187,14 +201,14 @@ pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result, VcpuError> { .try_into() // Safe to unwrap as Firecracker only targets 64-bit machines. .unwrap(); - reg_list = RegList::new(size).map_err(VcpuError::Fam)?; + reg_list = RegList::new(size).map_err(VcpuArchError::Fam)?; vcpufd .get_reg_list(&mut reg_list) - .map_err(VcpuError::GetRegList)?; + .map_err(VcpuArchError::GetRegList)?; Ok(reg_list.as_slice().to_vec()) } - _ => Err(VcpuError::GetRegList(e)), + _ => Err(VcpuArchError::GetRegList(e)), }, } } @@ -204,10 +218,10 @@ pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result, VcpuError> { /// # Arguments /// /// * `reg` - Register to be set. -pub fn set_register(vcpufd: &VcpuFd, reg: Aarch64RegisterRef) -> Result<(), VcpuError> { +pub fn set_register(vcpufd: &VcpuFd, reg: Aarch64RegisterRef) -> Result<(), VcpuArchError> { vcpufd .set_one_reg(reg.id, reg.as_slice()) - .map_err(|e| VcpuError::SetOneReg(reg.id, e))?; + .map_err(|e| VcpuArchError::SetOneReg(reg.id, e))?; Ok(()) } @@ -216,8 +230,8 @@ pub fn set_register(vcpufd: &VcpuFd, reg: Aarch64RegisterRef) -> Result<(), Vcpu /// # Arguments /// /// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. -pub fn get_mpstate(vcpufd: &VcpuFd) -> Result { - vcpufd.get_mp_state().map_err(VcpuError::GetMp) +pub fn get_mpstate(vcpufd: &VcpuFd) -> Result { + vcpufd.get_mp_state().map_err(VcpuArchError::GetMp) } /// Set the state of the system registers. @@ -226,18 +240,480 @@ pub fn get_mpstate(vcpufd: &VcpuFd) -> Result { /// /// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. /// * `state` - Structure for returning the state of the system registers. -pub fn set_mpstate(vcpufd: &VcpuFd, state: kvm_mp_state) -> Result<(), VcpuError> { - vcpufd.set_mp_state(state).map_err(VcpuError::SetMp) +pub fn set_mpstate(vcpufd: &VcpuFd, state: kvm_mp_state) -> Result<(), VcpuArchError> { + vcpufd.set_mp_state(state).map_err(VcpuArchError::SetMp) +} + +/// Errors associated with the wrappers over KVM ioctls. +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum KvmVcpuError { + /// Error configuring the vcpu registers: {0} + ConfigureRegisters(VcpuArchError), + /// Error creating vcpu: {0} + CreateVcpu(kvm_ioctls::Error), + /// Failed to dump CPU configuration: {0} + DumpCpuConfig(VcpuArchError), + /// Error getting the vcpu preferred target: {0} + GetPreferredTarget(kvm_ioctls::Error), + /// Error initializing the vcpu: {0} + Init(kvm_ioctls::Error), + /// Error applying template: {0} + ApplyCpuTemplate(VcpuArchError), + /// Failed to restore the state of the vcpu: {0} + RestoreState(VcpuArchError), + /// Failed to save the state of the vcpu: {0} + SaveState(VcpuArchError), +} + +/// Error type for [`KvmVcpu::configure`]. +pub type KvmVcpuConfigureError = KvmVcpuError; + +/// A wrapper around creating and using a kvm aarch64 vcpu. +#[derive(Debug)] +pub struct KvmVcpu { + /// Index of vcpu. + pub index: u8, + /// KVM vcpu fd. + pub fd: VcpuFd, + /// Vcpu peripherals, such as buses + pub peripherals: Peripherals, + mpidr: u64, + kvi: kvm_vcpu_init, +} + +/// Vcpu peripherals +#[derive(Default, Debug)] +pub struct Peripherals { + /// mmio bus. + pub mmio_bus: Option, +} + +impl KvmVcpu { + /// Constructs a new kvm vcpu with arch specific functionality. + /// + /// # Arguments + /// + /// * `index` - Represents the 0-based CPU index between [0, max vcpus). + /// * `vm` - The vm to which this vcpu will get attached. + pub fn new(index: u8, vm: &Vm) -> Result { + let kvm_vcpu = vm + .fd() + .create_vcpu(index.into()) + .map_err(KvmVcpuError::CreateVcpu)?; + + let mut kvi = Self::default_kvi(vm.fd())?; + // Secondary vcpus must be powered off for boot process. + if 0 < index { + kvi.features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF; + } + + Ok(KvmVcpu { + index, + fd: kvm_vcpu, + peripherals: Default::default(), + mpidr: 0, + kvi, + }) + } + + /// Gets the MPIDR register value. + pub fn get_mpidr(&self) -> u64 { + self.mpidr + } + + /// Configures an aarch64 specific vcpu for booting Linux. + /// + /// # Arguments + /// + /// * `guest_mem` - The guest memory used by this microvm. + /// * `kernel_entry_point` - Specifies the boot protocol and offset from `guest_mem` at which + /// the kernel starts. + /// * `vcpu_config` - The vCPU configuration. + pub fn configure( + &mut self, + guest_mem: &GuestMemoryMmap, + kernel_entry_point: EntryPoint, + vcpu_config: &VcpuConfig, + optional_capabilities: &OptionalCapabilities, + ) -> Result<(), KvmVcpuError> { + for reg in vcpu_config.cpu_config.regs.iter() { + self.fd.set_one_reg(reg.id, reg.as_slice()).map_err(|err| { + KvmVcpuError::ApplyCpuTemplate(VcpuArchError::SetOneReg(reg.id, err)) + })?; + } + + setup_boot_regs( + &self.fd, + self.index, + kernel_entry_point.entry_addr.raw_value(), + guest_mem, + optional_capabilities, + ) + .map_err(KvmVcpuError::ConfigureRegisters)?; + + self.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::ConfigureRegisters)?; + + Ok(()) + } + + /// Initializes an aarch64 specific vcpu for booting Linux. + /// + /// # Arguments + /// + /// * `vm_fd` - The kvm `VmFd` for this microvm. + pub fn init(&mut self, vcpu_features: &[VcpuFeatures]) -> Result<(), KvmVcpuError> { + for feature in vcpu_features.iter() { + let index = feature.index as usize; + self.kvi.features[index] = feature.bitmap.apply(self.kvi.features[index]); + } + + self.init_vcpu()?; + self.finalize_vcpu()?; + + Ok(()) + } + + /// Creates default kvi struct based on vcpu index. + pub fn default_kvi(vm_fd: &VmFd) -> Result { + let mut kvi = kvm_vcpu_init::default(); + // This reads back the kernel's preferred target type. + vm_fd + .get_preferred_target(&mut kvi) + .map_err(KvmVcpuError::GetPreferredTarget)?; + // We already checked that the capability is supported. + kvi.features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2; + + Ok(kvi) + } + + /// Save the KVM internal state. + pub fn save_state(&self) -> Result { + let mut state = VcpuState { + mp_state: get_mpstate(&self.fd).map_err(KvmVcpuError::SaveState)?, + ..Default::default() + }; + get_all_registers(&self.fd, &mut state.regs).map_err(KvmVcpuError::SaveState)?; + state.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::SaveState)?; + + state.kvi = self.kvi; + // We don't save power off state in a snapshot, because + // it was only needed during uVM boot process. + // When uVM is restored, the kernel has already passed + // the boot state and turned secondary vcpus on. + state.kvi.features[0] &= !(1 << KVM_ARM_VCPU_POWER_OFF); + + Ok(state) + } + + /// Use provided state to populate KVM internal state. + pub fn restore_state(&mut self, state: &VcpuState) -> Result<(), KvmVcpuError> { + self.kvi = state.kvi; + + self.init_vcpu()?; + + // If KVM_REG_ARM64_SVE_VLS is present it needs to + // be set before vcpu is finalized. + if let Some(sve_vls_reg) = state + .regs + .iter() + .find(|reg| reg.id == KVM_REG_ARM64_SVE_VLS) + { + set_register(&self.fd, sve_vls_reg).map_err(KvmVcpuError::RestoreState)?; + } + + self.finalize_vcpu()?; + + // KVM_REG_ARM64_SVE_VLS needs to be skipped after vcpu is finalized. + // If it is present it is handled in the code above. + for reg in state + .regs + .iter() + .filter(|reg| reg.id != KVM_REG_ARM64_SVE_VLS) + { + set_register(&self.fd, reg).map_err(KvmVcpuError::RestoreState)?; + } + set_mpstate(&self.fd, state.mp_state).map_err(KvmVcpuError::RestoreState)?; + Ok(()) + } + + /// Dumps CPU configuration. + pub fn dump_cpu_config(&self) -> Result { + let reg_list = get_all_registers_ids(&self.fd).map_err(KvmVcpuError::DumpCpuConfig)?; + + let mut regs = Aarch64RegisterVec::default(); + get_registers(&self.fd, ®_list, &mut regs).map_err(KvmVcpuError::DumpCpuConfig)?; + + Ok(CpuConfiguration { regs }) + } + /// Initializes internal vcpufd. + fn init_vcpu(&self) -> Result<(), KvmVcpuError> { + self.fd.vcpu_init(&self.kvi).map_err(KvmVcpuError::Init)?; + Ok(()) + } + + /// Checks for SVE feature and calls `vcpu_finalize` if + /// it is enabled. + fn finalize_vcpu(&self) -> Result<(), KvmVcpuError> { + if (self.kvi.features[0] & (1 << KVM_ARM_VCPU_SVE)) != 0 { + // KVM_ARM_VCPU_SVE has value 4 so casting to i32 is safe. + #[allow(clippy::cast_possible_wrap)] + let feature = KVM_ARM_VCPU_SVE as i32; + self.fd.vcpu_finalize(&feature).unwrap(); + } + Ok(()) + } +} + +impl Peripherals { + /// Runs the vCPU in KVM context and handles the kvm exit reason. + /// + /// Returns error or enum specifying whether emulation was handled or interrupted. + pub fn run_arch_emulation(&self, exit: VcpuExit) -> Result { + METRICS.vcpu.failures.inc(); + // TODO: Are we sure we want to finish running a vcpu upon + // receiving a vm exit that is not necessarily an error? + error!("Unexpected exit reason on vcpu run: {:?}", exit); + Err(VcpuError::UnhandledKvmExit(format!("{:?}", exit))) + } +} + +/// Structure holding VCPU kvm state. +#[derive(Default, Clone, Serialize, Deserialize)] +pub struct VcpuState { + /// Multiprocessing state. + pub mp_state: kvm_mp_state, + /// Vcpu registers. + pub regs: Aarch64RegisterVec, + /// We will be using the mpidr for passing it to the VmState. + /// The VmState will give this away for saving restoring the icc and redistributor + /// registers. + pub mpidr: u64, + /// kvi states for vcpu initialization. + pub kvi: kvm_vcpu_init, +} + +impl Debug for VcpuState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "kvm_mp_state: {:#x}", self.mp_state.mp_state)?; + writeln!(f, "mpidr: {:#x}", self.mpidr)?; + for reg in self.regs.iter() { + writeln!( + f, + "{:#x} 0x{}", + reg.id, + reg.as_slice() + .iter() + .rev() + .fold(String::new(), |mut output, b| { + let _ = write!(output, "{b:x}"); + output + }) + )?; + } + Ok(()) + } } #[cfg(test)] mod tests { #![allow(clippy::undocumented_unsafe_blocks)] + use std::os::unix::io::AsRawFd; + + use kvm_bindings::{KVM_ARM_VCPU_PSCI_0_2, KVM_REG_SIZE_U64}; + use vm_memory::GuestAddress; use super::*; + use crate::arch::BootProtocol; use crate::arch::aarch64::layout; + use crate::arch::aarch64::regs::Aarch64RegisterRef; + use crate::cpu_config::aarch64::CpuConfiguration; + use crate::cpu_config::templates::RegisterValueFilter; use crate::test_utils::arch_mem; + use crate::vcpu::VcpuConfig; use crate::vstate::kvm::Kvm; + use crate::vstate::memory::GuestMemoryMmap; + use crate::vstate::vm::Vm; + use crate::vstate::vm::tests::setup_vm_with_memory; + + fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { + let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + vcpu.init(&[]).unwrap(); + vm.setup_irqchip(1).unwrap(); + + (kvm, vm, vcpu, vm_mem) + } + + #[test] + fn test_create_vcpu() { + let (_, vm, _) = setup_vm_with_memory(0x1000); + + unsafe { libc::close(vm.fd().as_raw_fd()) }; + + let err = KvmVcpu::new(0, &vm); + assert_eq!( + err.err().unwrap().to_string(), + "Error creating vcpu: Bad file descriptor (os error 9)".to_string() + ); + + // dropping vm would double close the gic fd, so leak it + std::mem::forget(vm); + } + + #[test] + fn test_configure_vcpu() { + let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let optional_capabilities = kvm.optional_capabilities(); + + let vcpu_config = VcpuConfig { + vcpu_count: 1, + smt: false, + cpu_config: CpuConfiguration::default(), + }; + + vcpu.configure( + &vm_mem, + EntryPoint { + entry_addr: GuestAddress(crate::arch::get_kernel_start()), + protocol: BootProtocol::LinuxBoot, + }, + &vcpu_config, + &optional_capabilities, + ) + .unwrap(); + + unsafe { libc::close(vcpu.fd.as_raw_fd()) }; + + let err = vcpu.configure( + &vm_mem, + EntryPoint { + entry_addr: GuestAddress(crate::arch::get_kernel_start()), + protocol: BootProtocol::LinuxBoot, + }, + &vcpu_config, + &optional_capabilities, + ); + assert_eq!( + err.unwrap_err(), + KvmVcpuError::ConfigureRegisters(VcpuArchError::SetOneReg( + 0x6030000000100042, + kvm_ioctls::Error::new(9) + )) + ); + + // dropping vcpu would double close the gic fd, so leak it + std::mem::forget(vcpu); + } + + #[test] + fn test_init_vcpu() { + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + vm.setup_irqchip(1).unwrap(); + + // KVM_ARM_VCPU_PSCI_0_2 is set by default. + // we check if we can remove it. + let vcpu_features = vec![VcpuFeatures { + index: 0, + bitmap: RegisterValueFilter { + filter: 1 << KVM_ARM_VCPU_PSCI_0_2, + value: 0, + }, + }]; + vcpu.init(&vcpu_features).unwrap(); + assert!((vcpu.kvi.features[0] & (1 << KVM_ARM_VCPU_PSCI_0_2)) == 0) + } + + #[test] + fn test_vcpu_save_restore_state() { + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + vm.setup_irqchip(1).unwrap(); + + // Calling KVM_GET_REGLIST before KVM_VCPU_INIT will result in error. + let res = vcpu.save_state(); + assert!(matches!( + res.unwrap_err(), + KvmVcpuError::SaveState(VcpuArchError::GetRegList(_)) + )); + + // Try to restore the register using a faulty state. + let mut faulty_vcpu_state = VcpuState::default(); + + // Try faulty kvi state + let res = vcpu.restore_state(&faulty_vcpu_state); + assert!(matches!(res.unwrap_err(), KvmVcpuError::Init(_))); + + // Try faulty vcpu regs + faulty_vcpu_state.kvi = KvmVcpu::default_kvi(vm.fd()).unwrap(); + let mut regs = Aarch64RegisterVec::default(); + let mut reg = Aarch64RegisterRef::new(KVM_REG_SIZE_U64, &[0; 8]); + reg.id = 0; + regs.push(reg); + faulty_vcpu_state.regs = regs; + let res = vcpu.restore_state(&faulty_vcpu_state); + assert!(matches!( + res.unwrap_err(), + KvmVcpuError::RestoreState(VcpuArchError::SetOneReg(0, _)) + )); + + vcpu.init(&[]).unwrap(); + let state = vcpu.save_state().expect("Cannot save state of vcpu"); + assert!(!state.regs.is_empty()); + vcpu.restore_state(&state) + .expect("Cannot restore state of vcpu"); + } + + #[test] + fn test_dump_cpu_config_before_init() { + // Test `dump_cpu_config()` before `KVM_VCPU_INIT`. + // + // This should fail with ENOEXEC. + // https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165 + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let vcpu = KvmVcpu::new(0, &vm).unwrap(); + vm.setup_irqchip(1).unwrap(); + + vcpu.dump_cpu_config().unwrap_err(); + } + + #[test] + fn test_dump_cpu_config_after_init() { + // Test `dump_cpu_config()` after `KVM_VCPU_INIT`. + let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + vm.setup_irqchip(1).unwrap(); + vcpu.init(&[]).unwrap(); + + vcpu.dump_cpu_config().unwrap(); + } + + #[test] + fn test_setup_non_boot_vcpu() { + let (_, vm, _) = setup_vm_with_memory(0x1000); + let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap(); + vcpu1.init(&[]).unwrap(); + let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap(); + vcpu2.init(&[]).unwrap(); + } + + #[test] + fn test_get_valid_regs() { + // Test `get_regs()` with valid register IDs. + // - X0: 0x6030 0000 0010 0000 + // - X1: 0x6030 0000 0010 0002 + let (_, _, vcpu, _) = setup_vcpu(0x10000); + let reg_list = Vec::::from([0x6030000000100000, 0x6030000000100002]); + get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap(); + } + + #[test] + fn test_get_invalid_regs() { + // Test `get_regs()` with invalid register IDs. + let (_, _, vcpu, _) = setup_vcpu(0x10000); + let reg_list = Vec::::from([0x6030000000100001, 0x6030000000100003]); + get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap_err(); + } #[test] fn test_setup_regs() { @@ -250,7 +726,7 @@ mod tests { let res = setup_boot_regs(&vcpu, 0, 0x0, &mem, &optional_capabilities); assert!(matches!( res.unwrap_err(), - VcpuError::SetOneReg(0x6030000000100042, _) + VcpuArchError::SetOneReg(0x6030000000100042, _) )); let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); @@ -291,7 +767,7 @@ mod tests { let res = get_mpidr(&vcpu); assert!(matches!( res.unwrap_err(), - VcpuError::GetOneReg(MPIDR_EL1, _) + VcpuArchError::GetOneReg(MPIDR_EL1, _) )); vcpu.vcpu_init(&kvi).unwrap(); @@ -309,7 +785,7 @@ mod tests { // Must fail when vcpu is not initialized yet. let mut regs = Aarch64RegisterVec::default(); let res = get_all_registers(&vcpu, &mut regs); - assert!(matches!(res.unwrap_err(), VcpuError::GetRegList(_))); + assert!(matches!(res.unwrap_err(), VcpuArchError::GetRegList(_))); vcpu.vcpu_init(&kvi).unwrap(); get_all_registers(&vcpu, &mut regs).unwrap(); @@ -334,10 +810,10 @@ mod tests { unsafe { libc::close(vcpu.as_raw_fd()) }; let res = get_mpstate(&vcpu); - assert!(matches!(res, Err(VcpuError::GetMp(_))), "{:?}", res); + assert!(matches!(res, Err(VcpuArchError::GetMp(_))), "{:?}", res); let res = set_mpstate(&vcpu, kvm_mp_state::default()); - assert!(matches!(res, Err(VcpuError::SetMp(_))), "{:?}", res); + assert!(matches!(res, Err(VcpuArchError::SetMp(_))), "{:?}", res); // dropping vcpu would double close the fd, so leak it std::mem::forget(vcpu); diff --git a/src/vmm/src/vstate/vm/aarch64.rs b/src/vmm/src/arch/aarch64/vm.rs similarity index 90% rename from src/vmm/src/vstate/vm/aarch64.rs rename to src/vmm/src/arch/aarch64/vm.rs index 5f22e1432ee..d1b6f07663f 100644 --- a/src/vmm/src/vstate/vm/aarch64.rs +++ b/src/vmm/src/arch/aarch64/vm.rs @@ -4,14 +4,15 @@ use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; -use super::VmError; use crate::Kvm; use crate::arch::aarch64::gic::GicState; +use crate::vstate::vm::VmError; /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] pub struct ArchVm { - pub(super) fd: VmFd, + /// KVM file descriptor of microVM + pub fd: VmFd, // On aarch64 we need to keep around the fd obtained by creating the VGIC device. irqchip_handle: Option, } @@ -37,11 +38,13 @@ impl ArchVm { }) } - pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + /// Pre-vCPU creation setup. + pub fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { Ok(()) } - pub(super) fn arch_post_create_vcpus(&mut self, nr_vcpus: u8) -> Result<(), ArchVmError> { + /// Post-vCPU creation setup. + pub fn arch_post_create_vcpus(&mut self, nr_vcpus: u8) -> Result<(), ArchVmError> { // On aarch64, the vCPUs need to be created (i.e call KVM_CREATE_VCPU) before setting up the // IRQ chip because the `KVM_CREATE_VCPU` ioctl will return error if the IRQCHIP // was already initialized. diff --git a/src/vmm/src/arch/aarch64/vstate/mod.rs b/src/vmm/src/arch/aarch64/vstate/mod.rs deleted file mode 100644 index c544a04628a..00000000000 --- a/src/vmm/src/arch/aarch64/vstate/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -/// Architecture specific KVM-related code -pub mod kvm; diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 107729bbb1b..dd3ae178127 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -13,7 +13,11 @@ use vm_memory::GuestAddress; pub mod aarch64; #[cfg(target_arch = "aarch64")] -pub use aarch64::vstate::kvm::{Kvm, KvmArchError, OptionalCapabilities}; +pub use aarch64::kvm::{Kvm, KvmArchError, OptionalCapabilities}; +#[cfg(target_arch = "aarch64")] +pub use aarch64::vcpu::*; +#[cfg(target_arch = "aarch64")] +pub use aarch64::vm::{ArchVm, ArchVmError, VmState}; #[cfg(target_arch = "aarch64")] pub use aarch64::{ ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, @@ -26,14 +30,18 @@ pub use aarch64::{ pub mod x86_64; #[cfg(target_arch = "x86_64")] -pub use crate::arch::x86_64::{ +pub use x86_64::kvm::{Kvm, KvmArchError}; +#[cfg(target_arch = "x86_64")] +pub use x86_64::vcpu::*; +#[cfg(target_arch = "x86_64")] +pub use x86_64::vm::{ArchVm, ArchVmError, VmState}; +#[cfg(target_arch = "x86_64")] +pub use x86_64::{ ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::CMDLINE_MAX_SIZE, layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, }; -#[cfg(target_arch = "x86_64")] -pub use x86_64::vstate::kvm::{Kvm, KvmArchError}; /// Types of devices that can get attached to this platform. #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)] @@ -83,7 +91,7 @@ impl fmt::Display for DeviceType { } } -/// Suported boot protocols for +/// Supported boot protocols for #[derive(Debug, Copy, Clone, PartialEq)] pub enum BootProtocol { /// Linux 64-bit boot protocol diff --git a/src/vmm/src/arch/x86_64/vstate/kvm.rs b/src/vmm/src/arch/x86_64/kvm.rs similarity index 100% rename from src/vmm/src/arch/x86_64/vstate/kvm.rs rename to src/vmm/src/arch/x86_64/kvm.rs diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index c01c8cd79e4..24a7de7ec8a 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -12,6 +12,8 @@ pub mod cpu_model; mod gdt; /// Contains logic for setting up Advanced Programmable Interrupt Controller (local version). pub mod interrupts; +/// Architecture specific KVM-related code +pub mod kvm; /// Layout for the x86_64 system. pub mod layout; mod mptable; @@ -19,8 +21,10 @@ mod mptable; pub mod msr; /// Logic for configuring x86_64 registers. pub mod regs; -/// Architecture specific microVM state. -pub mod vstate; +/// Architecture specific vCPU code +pub mod vcpu; +/// Architecture specific VM state code +pub mod vm; /// Logic for configuring XSTATE features. pub mod xstate; diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/arch/x86_64/vcpu.rs similarity index 99% rename from src/vmm/src/vstate/vcpu/x86_64.rs rename to src/vmm/src/arch/x86_64/vcpu.rs index d4d6df12c16..3cf53cdefc1 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/arch/x86_64/vcpu.rs @@ -25,7 +25,7 @@ use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecial use crate::cpu_config::x86_64::{CpuConfiguration, cpuid}; use crate::logger::{IncMetric, METRICS}; use crate::vstate::memory::GuestMemoryMmap; -use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation}; +use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation, VcpuError}; use crate::vstate::vm::Vm; // Tolerance for TSC frequency expected variation. @@ -145,7 +145,7 @@ pub struct KvmVcpu { /// KVM vcpu fd. pub fd: VcpuFd, /// Vcpu peripherals, such as buses - pub(super) peripherals: Peripherals, + pub peripherals: Peripherals, /// The list of MSRs to include in a VM snapshot, in the same order as KVM returned them /// from KVM_GET_MSR_INDEX_LIST msrs_to_save: Vec, @@ -157,7 +157,7 @@ pub struct KvmVcpu { /// Vcpu peripherals #[derive(Default, Debug)] -pub(super) struct Peripherals { +pub struct Peripherals { /// Pio bus. pub pio_bus: Option, /// Mmio bus. @@ -334,7 +334,7 @@ impl KvmVcpu { /// /// # Errors /// - /// When [`kvm_ioctls::VcpuFd::get_tsc_khz`] errrors. + /// When [`kvm_ioctls::VcpuFd::get_tsc_khz`] errors. pub fn get_tsc_khz(&self) -> Result { let res = self.fd.get_tsc_khz()?; Ok(res) @@ -477,7 +477,7 @@ impl KvmVcpu { /// # Arguments /// /// * `msr_index_iter`: Iterator over MSR indices. - /// * `chunk_size`: Lenght of a chunk. + /// * `chunk_size`: Length of a chunk. /// /// # Errors /// @@ -504,7 +504,7 @@ impl KvmVcpu { .map_err(KvmVcpuError::VcpuGetMsrs)?; // GET_MSRS returns a number of successfully set msrs. // If number of set msrs is not equal to the length of - // `msrs`, then the value retuned by GET_MSRS can act + // `msrs`, then the value returned by GET_MSRS can act // as an index to the problematic msr. if nmsrs != chunk_size { Err(KvmVcpuError::VcpuGetMsr(msrs.as_slice()[nmsrs].index)) @@ -621,7 +621,7 @@ impl KvmVcpu { // in the state. If they are different, we need to // scale the TSC to the freq found in the state. // We accept values within a tolerance of 250 parts - // per million beacuse it is common for TSC frequency + // per million because it is common for TSC frequency // to differ due to calibration at boot time. let diff = (i64::from(self.get_tsc_khz()?) - i64::from(state_tsc_freq)).abs(); // Cannot overflow since u32::MAX * 250 < i64::MAX @@ -705,7 +705,7 @@ impl Peripherals { /// Runs the vCPU in KVM context and handles the kvm exit reason. /// /// Returns error or enum specifying whether emulation was handled or interrupted. - pub fn run_arch_emulation(&self, exit: VcpuExit) -> Result { + pub fn run_arch_emulation(&self, exit: VcpuExit) -> Result { match exit { VcpuExit::IoIn(addr, data) => { if let Some(pio_bus) = &self.pio_bus { @@ -728,7 +728,7 @@ impl Peripherals { // TODO: Are we sure we want to finish running a vcpu upon // receiving a vm exit that is not necessarily an error? error!("Unexpected exit reason on vcpu run: {:?}", unexpected_exit); - Err(super::VcpuError::UnhandledKvmExit(format!( + Err(VcpuError::UnhandledKvmExit(format!( "{:?}", unexpected_exit ))) diff --git a/src/vmm/src/vstate/vm/x86_64.rs b/src/vmm/src/arch/x86_64/vm.rs similarity index 97% rename from src/vmm/src/vstate/vm/x86_64.rs rename to src/vmm/src/arch/x86_64/vm.rs index 69bad36c09e..ebce8ef02d0 100644 --- a/src/vmm/src/vstate/vm/x86_64.rs +++ b/src/vmm/src/arch/x86_64/vm.rs @@ -48,7 +48,8 @@ pub enum ArchVmError { /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] pub struct ArchVm { - pub(super) fd: VmFd, + /// KVM file descriptor of microVM + pub fd: VmFd, msrs_to_save: MsrList, /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct. /// @@ -93,12 +94,14 @@ impl ArchVm { }) } - pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + /// Pre-vCPU creation setup. + pub fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS` self.setup_irqchip() } - pub(super) fn arch_post_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { + /// Post-vCPU creation setup. + pub fn arch_post_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> { Ok(()) } diff --git a/src/vmm/src/arch/x86_64/vstate/mod.rs b/src/vmm/src/arch/x86_64/vstate/mod.rs deleted file mode 100644 index c544a04628a..00000000000 --- a/src/vmm/src/arch/x86_64/vstate/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -/// Architecture specific KVM-related code -pub mod kvm; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 476bbc365c9..ae9cab9e51c 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -420,10 +420,10 @@ pub enum BuildMicrovmFromSnapshotError { TscFrequencyNotPresent, #[cfg(target_arch = "x86_64")] /// Could not get TSC to check if TSC scaling was required with the snapshot: {0} - GetTsc(#[from] crate::vstate::vcpu::GetTscError), + GetTsc(#[from] crate::arch::GetTscError), #[cfg(target_arch = "x86_64")] /// Could not set TSC scaling within the snapshot: {0} - SetTsc(#[from] crate::vstate::vcpu::SetTscError), + SetTsc(#[from] crate::arch::SetTscError), /// Failed to restore microVM state: {0} RestoreState(#[from] crate::vstate::vm::ArchVmError), /// Failed to update microVM configuration: {0} diff --git a/src/vmm/src/cpu_config/aarch64/mod.rs b/src/vmm/src/cpu_config/aarch64/mod.rs index d11a4f8c0ab..26ca48572ac 100644 --- a/src/vmm/src/cpu_config/aarch64/mod.rs +++ b/src/vmm/src/cpu_config/aarch64/mod.rs @@ -10,12 +10,12 @@ pub mod test_utils; use super::templates::CustomCpuTemplate; use crate::arch::aarch64::regs::{Aarch64RegisterVec, RegSize}; -use crate::arch::aarch64::vcpu::VcpuError as ArchError; +use crate::arch::aarch64::vcpu::VcpuArchError; /// Errors thrown while configuring templates. #[derive(Debug, PartialEq, Eq, thiserror::Error)] #[error("Failed to create a guest cpu configuration: {0}")] -pub struct CpuConfigurationError(#[from] pub ArchError); +pub struct CpuConfigurationError(#[from] pub VcpuArchError); /// CPU configuration for aarch64 #[derive(Debug, Default, Clone, PartialEq, Eq)] diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index c9d71e1f14a..c3293db1607 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -33,7 +33,7 @@ use vm_memory::{Bytes, GuestAddress, GuestMemoryError}; use super::arch; use crate::arch::GUEST_PAGE_SIZE; #[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::vcpu::VcpuError as AarchVcpuError; +use crate::arch::aarch64::vcpu::VcpuArchError as AarchVcpuError; use crate::logger::{error, info}; use crate::utils::u64_to_usize; use crate::vstate::vcpu::VcpuSendEventError; diff --git a/src/vmm/src/vstate/vcpu/mod.rs b/src/vmm/src/vstate/vcpu.rs similarity index 99% rename from src/vmm/src/vstate/vcpu/mod.rs rename to src/vmm/src/vstate/vcpu.rs index a04177cd938..d54d7de759b 100644 --- a/src/vmm/src/vstate/vcpu/mod.rs +++ b/src/vmm/src/vstate/vcpu.rs @@ -23,6 +23,7 @@ use vmm_sys_util::errno; use vmm_sys_util::eventfd::EventFd; use crate::FcExitCode; +pub use crate::arch::{KvmVcpu, KvmVcpuConfigureError, KvmVcpuError, Peripherals, VcpuState}; use crate::cpu_config::templates::{CpuConfiguration, GuestConfigError}; #[cfg(feature = "gdb")] use crate::gdb::target::{GdbTargetError, get_raw_tid}; @@ -32,18 +33,6 @@ use crate::utils::signal::{Killable, register_signal_handler, sigrtmin}; use crate::utils::sm::StateMachine; use crate::vstate::vm::Vm; -/// Module with aarch64 vCPU implementation. -#[cfg(target_arch = "aarch64")] -pub mod aarch64; -/// Module with x86_64 vCPU implementation. -#[cfg(target_arch = "x86_64")] -pub mod x86_64; - -#[cfg(target_arch = "aarch64")] -pub use aarch64::{KvmVcpuError, *}; -#[cfg(target_arch = "x86_64")] -pub use x86_64::{KvmVcpuError, *}; - /// Signal number (SIGRTMIN) used to kick Vcpus. pub const VCPU_RTSIG_OFFSET: i32 = 0; diff --git a/src/vmm/src/vstate/vcpu/aarch64.rs b/src/vmm/src/vstate/vcpu/aarch64.rs deleted file mode 100644 index 98972c796d2..00000000000 --- a/src/vmm/src/vstate/vcpu/aarch64.rs +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the THIRD-PARTY file. - -use std::fmt::{Debug, Write}; - -use kvm_bindings::{ - KVM_ARM_VCPU_POWER_OFF, KVM_ARM_VCPU_PSCI_0_2, KVM_ARM_VCPU_SVE, kvm_mp_state, kvm_vcpu_init, -}; -use kvm_ioctls::*; -use serde::{Deserialize, Serialize}; - -use crate::arch::EntryPoint; -use crate::arch::aarch64::regs::{Aarch64RegisterVec, KVM_REG_ARM64_SVE_VLS}; -use crate::arch::aarch64::vcpu::{ - VcpuError as ArchError, get_all_registers, get_all_registers_ids, get_mpidr, get_mpstate, - get_registers, set_mpstate, set_register, setup_boot_regs, -}; -use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures; -use crate::cpu_config::templates::CpuConfiguration; -use crate::logger::{IncMetric, METRICS, error}; -use crate::vcpu::{VcpuConfig, VcpuError}; -use crate::vstate::kvm::OptionalCapabilities; -use crate::vstate::memory::{Address, GuestMemoryMmap}; -use crate::vstate::vcpu::VcpuEmulation; -use crate::vstate::vm::Vm; - -/// Errors associated with the wrappers over KVM ioctls. -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] -pub enum KvmVcpuError { - /// Error configuring the vcpu registers: {0} - ConfigureRegisters(ArchError), - /// Error creating vcpu: {0} - CreateVcpu(kvm_ioctls::Error), - /// Failed to dump CPU configuration: {0} - DumpCpuConfig(ArchError), - /// Error getting the vcpu preferred target: {0} - GetPreferredTarget(kvm_ioctls::Error), - /// Error initializing the vcpu: {0} - Init(kvm_ioctls::Error), - /// Error applying template: {0} - ApplyCpuTemplate(ArchError), - /// Failed to restore the state of the vcpu: {0} - RestoreState(ArchError), - /// Failed to save the state of the vcpu: {0} - SaveState(ArchError), -} - -/// Error type for [`KvmVcpu::configure`]. -pub type KvmVcpuConfigureError = KvmVcpuError; - -/// A wrapper around creating and using a kvm aarch64 vcpu. -#[derive(Debug)] -pub struct KvmVcpu { - /// Index of vcpu. - pub index: u8, - /// KVM vcpu fd. - pub fd: VcpuFd, - /// Vcpu peripherals, such as buses - pub(super) peripherals: Peripherals, - mpidr: u64, - kvi: kvm_vcpu_init, -} - -/// Vcpu peripherals -#[derive(Default, Debug)] -pub(super) struct Peripherals { - /// mmio bus. - pub mmio_bus: Option, -} - -impl KvmVcpu { - /// Constructs a new kvm vcpu with arch specific functionality. - /// - /// # Arguments - /// - /// * `index` - Represents the 0-based CPU index between [0, max vcpus). - /// * `vm` - The vm to which this vcpu will get attached. - pub fn new(index: u8, vm: &Vm) -> Result { - let kvm_vcpu = vm - .fd() - .create_vcpu(index.into()) - .map_err(KvmVcpuError::CreateVcpu)?; - - let mut kvi = Self::default_kvi(vm.fd())?; - // Secondary vcpus must be powered off for boot process. - if 0 < index { - kvi.features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF; - } - - Ok(KvmVcpu { - index, - fd: kvm_vcpu, - peripherals: Default::default(), - mpidr: 0, - kvi, - }) - } - - /// Gets the MPIDR register value. - pub fn get_mpidr(&self) -> u64 { - self.mpidr - } - - /// Configures an aarch64 specific vcpu for booting Linux. - /// - /// # Arguments - /// - /// * `guest_mem` - The guest memory used by this microvm. - /// * `kernel_entry_point` - Specifies the boot protocol and offset from `guest_mem` at which - /// the kernel starts. - /// * `vcpu_config` - The vCPU configuration. - pub fn configure( - &mut self, - guest_mem: &GuestMemoryMmap, - kernel_entry_point: EntryPoint, - vcpu_config: &VcpuConfig, - optional_capabilities: &OptionalCapabilities, - ) -> Result<(), KvmVcpuError> { - for reg in vcpu_config.cpu_config.regs.iter() { - self.fd - .set_one_reg(reg.id, reg.as_slice()) - .map_err(|err| KvmVcpuError::ApplyCpuTemplate(ArchError::SetOneReg(reg.id, err)))?; - } - - setup_boot_regs( - &self.fd, - self.index, - kernel_entry_point.entry_addr.raw_value(), - guest_mem, - optional_capabilities, - ) - .map_err(KvmVcpuError::ConfigureRegisters)?; - - self.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::ConfigureRegisters)?; - - Ok(()) - } - - /// Initializes an aarch64 specific vcpu for booting Linux. - /// - /// # Arguments - /// - /// * `vm_fd` - The kvm `VmFd` for this microvm. - pub fn init(&mut self, vcpu_features: &[VcpuFeatures]) -> Result<(), KvmVcpuError> { - for feature in vcpu_features.iter() { - let index = feature.index as usize; - self.kvi.features[index] = feature.bitmap.apply(self.kvi.features[index]); - } - - self.init_vcpu()?; - self.finalize_vcpu()?; - - Ok(()) - } - - /// Creates default kvi struct based on vcpu index. - pub fn default_kvi(vm_fd: &VmFd) -> Result { - let mut kvi = kvm_vcpu_init::default(); - // This reads back the kernel's preferred target type. - vm_fd - .get_preferred_target(&mut kvi) - .map_err(KvmVcpuError::GetPreferredTarget)?; - // We already checked that the capability is supported. - kvi.features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2; - - Ok(kvi) - } - - /// Save the KVM internal state. - pub fn save_state(&self) -> Result { - let mut state = VcpuState { - mp_state: get_mpstate(&self.fd).map_err(KvmVcpuError::SaveState)?, - ..Default::default() - }; - get_all_registers(&self.fd, &mut state.regs).map_err(KvmVcpuError::SaveState)?; - state.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::SaveState)?; - - state.kvi = self.kvi; - // We don't save power off state in a snapshot, because - // it was only needed during uVM boot process. - // When uVM is restored, the kernel has already passed - // the boot state and turned secondary vcpus on. - state.kvi.features[0] &= !(1 << KVM_ARM_VCPU_POWER_OFF); - - Ok(state) - } - - /// Use provided state to populate KVM internal state. - pub fn restore_state(&mut self, state: &VcpuState) -> Result<(), KvmVcpuError> { - self.kvi = state.kvi; - - self.init_vcpu()?; - - // If KVM_REG_ARM64_SVE_VLS is present it needs to - // be set before vcpu is finalized. - if let Some(sve_vls_reg) = state - .regs - .iter() - .find(|reg| reg.id == KVM_REG_ARM64_SVE_VLS) - { - set_register(&self.fd, sve_vls_reg).map_err(KvmVcpuError::RestoreState)?; - } - - self.finalize_vcpu()?; - - // KVM_REG_ARM64_SVE_VLS needs to be skipped after vcpu is finalized. - // If it is present it is handled in the code above. - for reg in state - .regs - .iter() - .filter(|reg| reg.id != KVM_REG_ARM64_SVE_VLS) - { - set_register(&self.fd, reg).map_err(KvmVcpuError::RestoreState)?; - } - set_mpstate(&self.fd, state.mp_state).map_err(KvmVcpuError::RestoreState)?; - Ok(()) - } - - /// Dumps CPU configuration. - pub fn dump_cpu_config(&self) -> Result { - let reg_list = get_all_registers_ids(&self.fd).map_err(KvmVcpuError::DumpCpuConfig)?; - - let mut regs = Aarch64RegisterVec::default(); - get_registers(&self.fd, ®_list, &mut regs).map_err(KvmVcpuError::DumpCpuConfig)?; - - Ok(CpuConfiguration { regs }) - } - /// Initializes internal vcpufd. - fn init_vcpu(&self) -> Result<(), KvmVcpuError> { - self.fd.vcpu_init(&self.kvi).map_err(KvmVcpuError::Init)?; - Ok(()) - } - - /// Checks for SVE feature and calls `vcpu_finalize` if - /// it is enabled. - fn finalize_vcpu(&self) -> Result<(), KvmVcpuError> { - if (self.kvi.features[0] & (1 << KVM_ARM_VCPU_SVE)) != 0 { - // KVM_ARM_VCPU_SVE has value 4 so casting to i32 is safe. - #[allow(clippy::cast_possible_wrap)] - let feature = KVM_ARM_VCPU_SVE as i32; - self.fd.vcpu_finalize(&feature).unwrap(); - } - Ok(()) - } -} - -impl Peripherals { - /// Runs the vCPU in KVM context and handles the kvm exit reason. - /// - /// Returns error or enum specifying whether emulation was handled or interrupted. - pub fn run_arch_emulation(&self, exit: VcpuExit) -> Result { - METRICS.vcpu.failures.inc(); - // TODO: Are we sure we want to finish running a vcpu upon - // receiving a vm exit that is not necessarily an error? - error!("Unexpected exit reason on vcpu run: {:?}", exit); - Err(VcpuError::UnhandledKvmExit(format!("{:?}", exit))) - } -} - -/// Structure holding VCPU kvm state. -#[derive(Default, Clone, Serialize, Deserialize)] -pub struct VcpuState { - /// Multiprocessing state. - pub mp_state: kvm_mp_state, - /// Vcpu registers. - pub regs: Aarch64RegisterVec, - /// We will be using the mpidr for passing it to the VmState. - /// The VmState will give this away for saving restoring the icc and redistributor - /// registers. - pub mpidr: u64, - /// kvi states for vcpu initialization. - pub kvi: kvm_vcpu_init, -} - -impl Debug for VcpuState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "kvm_mp_state: {:#x}", self.mp_state.mp_state)?; - writeln!(f, "mpidr: {:#x}", self.mpidr)?; - for reg in self.regs.iter() { - writeln!( - f, - "{:#x} 0x{}", - reg.id, - reg.as_slice() - .iter() - .rev() - .fold(String::new(), |mut output, b| { - let _ = write!(output, "{b:x}"); - output - }) - )?; - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - #![allow(clippy::undocumented_unsafe_blocks)] - use std::os::unix::io::AsRawFd; - - use kvm_bindings::{KVM_ARM_VCPU_PSCI_0_2, KVM_REG_SIZE_U64}; - use vm_memory::GuestAddress; - - use super::*; - use crate::arch::BootProtocol; - use crate::arch::aarch64::regs::Aarch64RegisterRef; - use crate::cpu_config::aarch64::CpuConfiguration; - use crate::cpu_config::templates::RegisterValueFilter; - use crate::vcpu::VcpuConfig; - use crate::vstate::kvm::Kvm; - use crate::vstate::memory::GuestMemoryMmap; - use crate::vstate::vm::Vm; - use crate::vstate::vm::tests::setup_vm_with_memory; - - fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { - let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); - vcpu.init(&[]).unwrap(); - vm.setup_irqchip(1).unwrap(); - - (kvm, vm, vcpu, vm_mem) - } - - #[test] - fn test_create_vcpu() { - let (_, vm, _) = setup_vm_with_memory(0x1000); - - unsafe { libc::close(vm.fd().as_raw_fd()) }; - - let err = KvmVcpu::new(0, &vm); - assert_eq!( - err.err().unwrap().to_string(), - "Error creating vcpu: Bad file descriptor (os error 9)".to_string() - ); - - // dropping vm would double close the gic fd, so leak it - std::mem::forget(vm); - } - - #[test] - fn test_configure_vcpu() { - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); - let optional_capabilities = kvm.optional_capabilities(); - - let vcpu_config = VcpuConfig { - vcpu_count: 1, - smt: false, - cpu_config: CpuConfiguration::default(), - }; - - vcpu.configure( - &vm_mem, - EntryPoint { - entry_addr: GuestAddress(crate::arch::get_kernel_start()), - protocol: BootProtocol::LinuxBoot, - }, - &vcpu_config, - &optional_capabilities, - ) - .unwrap(); - - unsafe { libc::close(vcpu.fd.as_raw_fd()) }; - - let err = vcpu.configure( - &vm_mem, - EntryPoint { - entry_addr: GuestAddress(crate::arch::get_kernel_start()), - protocol: BootProtocol::LinuxBoot, - }, - &vcpu_config, - &optional_capabilities, - ); - assert_eq!( - err.unwrap_err(), - KvmVcpuError::ConfigureRegisters(ArchError::SetOneReg( - 0x6030000000100042, - kvm_ioctls::Error::new(9) - )) - ); - - // dropping vcpu would double close the gic fd, so leak it - std::mem::forget(vcpu); - } - - #[test] - fn test_init_vcpu() { - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); - vm.setup_irqchip(1).unwrap(); - - // KVM_ARM_VCPU_PSCI_0_2 is set by default. - // we check if we can remove it. - let vcpu_features = vec![VcpuFeatures { - index: 0, - bitmap: RegisterValueFilter { - filter: 1 << KVM_ARM_VCPU_PSCI_0_2, - value: 0, - }, - }]; - vcpu.init(&vcpu_features).unwrap(); - assert!((vcpu.kvi.features[0] & (1 << KVM_ARM_VCPU_PSCI_0_2)) == 0) - } - - #[test] - fn test_vcpu_save_restore_state() { - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); - vm.setup_irqchip(1).unwrap(); - - // Calling KVM_GET_REGLIST before KVM_VCPU_INIT will result in error. - let res = vcpu.save_state(); - assert!(matches!( - res.unwrap_err(), - KvmVcpuError::SaveState(ArchError::GetRegList(_)) - )); - - // Try to restore the register using a faulty state. - let mut faulty_vcpu_state = VcpuState::default(); - - // Try faulty kvi state - let res = vcpu.restore_state(&faulty_vcpu_state); - assert!(matches!(res.unwrap_err(), KvmVcpuError::Init(_))); - - // Try faulty vcpu regs - faulty_vcpu_state.kvi = KvmVcpu::default_kvi(vm.fd()).unwrap(); - let mut regs = Aarch64RegisterVec::default(); - let mut reg = Aarch64RegisterRef::new(KVM_REG_SIZE_U64, &[0; 8]); - reg.id = 0; - regs.push(reg); - faulty_vcpu_state.regs = regs; - let res = vcpu.restore_state(&faulty_vcpu_state); - assert!(matches!( - res.unwrap_err(), - KvmVcpuError::RestoreState(ArchError::SetOneReg(0, _)) - )); - - vcpu.init(&[]).unwrap(); - let state = vcpu.save_state().expect("Cannot save state of vcpu"); - assert!(!state.regs.is_empty()); - vcpu.restore_state(&state) - .expect("Cannot restore state of vcpu"); - } - - #[test] - fn test_dump_cpu_config_before_init() { - // Test `dump_cpu_config()` before `KVM_VCPU_INIT`. - // - // This should fail with ENOEXEC. - // https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165 - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - let vcpu = KvmVcpu::new(0, &vm).unwrap(); - vm.setup_irqchip(1).unwrap(); - - vcpu.dump_cpu_config().unwrap_err(); - } - - #[test] - fn test_dump_cpu_config_after_init() { - // Test `dump_cpu_config()` after `KVM_VCPU_INIT`. - let (_, mut vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); - vm.setup_irqchip(1).unwrap(); - vcpu.init(&[]).unwrap(); - - vcpu.dump_cpu_config().unwrap(); - } - - #[test] - fn test_setup_non_boot_vcpu() { - let (_, vm, _) = setup_vm_with_memory(0x1000); - let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap(); - vcpu1.init(&[]).unwrap(); - let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap(); - vcpu2.init(&[]).unwrap(); - } - - #[test] - fn test_get_valid_regs() { - // Test `get_regs()` with valid register IDs. - // - X0: 0x6030 0000 0010 0000 - // - X1: 0x6030 0000 0010 0002 - let (_, _, vcpu, _) = setup_vcpu(0x10000); - let reg_list = Vec::::from([0x6030000000100000, 0x6030000000100002]); - get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap(); - } - - #[test] - fn test_get_invalid_regs() { - // Test `get_regs()` with invalid register IDs. - let (_, _, vcpu, _) = setup_vcpu(0x10000); - let reg_list = Vec::::from([0x6030000000100001, 0x6030000000100003]); - get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap_err(); - } -} diff --git a/src/vmm/src/vstate/vm/mod.rs b/src/vmm/src/vstate/vm.rs similarity index 95% rename from src/vmm/src/vstate/vm/mod.rs rename to src/vmm/src/vstate/vm.rs index 49c65bd92ed..4292c2f2f49 100644 --- a/src/vmm/src/vstate/vm/mod.rs +++ b/src/vmm/src/vstate/vm.rs @@ -9,19 +9,10 @@ use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; +use crate::Vcpu; +pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState}; use crate::logger::info; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; - -#[cfg(target_arch = "x86_64")] -#[path = "x86_64.rs"] -mod arch; -#[cfg(target_arch = "aarch64")] -#[path = "aarch64.rs"] -mod arch; - -pub use arch::{ArchVm as Vm, ArchVmError, VmState}; - -use crate::Vcpu; use crate::vstate::vcpu::VcpuError; /// Errors associated with the wrappers over KVM ioctls. @@ -43,7 +34,8 @@ pub enum VmError { /// Contains Vm functions that are usable across CPU architectures impl Vm { - fn create_vm(kvm: &crate::vstate::kvm::Kvm) -> Result { + /// Create a KVM VM + pub fn create_vm(kvm: &crate::vstate::kvm::Kvm) -> Result { // It is known that KVM_CREATE_VM occasionally fails with EINTR on heavily loaded machines // with many VMs. // @@ -57,7 +49,7 @@ impl Vm { // KVM_CREATE_VM returns EINTR. // https://lore.kernel.org/qemu-devel/8735e0s1zw.wl-maz@kernel.org/ // - // To mitigate it, QEMU does an inifinite retry on EINTR that greatly improves reliabiliy: + // To mitigate it, QEMU does an infinite retry on EINTR that greatly improves reliabiliy: // - https://github.com/qemu/qemu/commit/94ccff133820552a859c0fb95e33a539e0b90a75 // - https://github.com/qemu/qemu/commit/bbde13cd14ad4eec18529ce0bf5876058464e124 // From 6b5f4b191b338350bf6cc017b6f26ce9c24346dc Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 15:34:38 +0000 Subject: [PATCH 411/464] refactor: don't duplicate VIRTIO_F_* constants in generated modules Add a dedicated virtio_config.rs module that is bindgen'd from virtio_config.h and contains exactly the VIRTIO_F constants. This avoid the VIRTIO_F constants being redefined across bindgen'd modules for the block, net and rng devices (or in the case of the balloon device, avoids one device using another's bindgen module). Since this completely eliminates all contents from virtio_rng.rs, delete that module. Note that for some reason, my laptop's virtio_config.h was missing half the constants, despite upstream 6.8 headers containing them. So I bindgen'd this file on a .metal where all the constants were present in the header. Lastly, there's the question of the vsock modules, which has manually written bindings in the uapi module, contained in `vsock/mod.rs`. I tried autogenerating these, but bindgen chokes on the enum-constants contained in virtio_vsock.h, so I'm leaving that as-is for now, apart from deduplicating the VIRTIO_F_* constants. Signed-off-by: Patrick Roy --- src/vmm/src/devices/virtio/balloon/device.rs | 2 +- .../src/devices/virtio/block/vhost_user/device.rs | 5 ++--- src/vmm/src/devices/virtio/block/virtio/device.rs | 3 ++- src/vmm/src/devices/virtio/generated/mod.rs | 2 +- src/vmm/src/devices/virtio/generated/virtio_blk.rs | 13 ------------- .../generated/{virtio_rng.rs => virtio_config.rs} | 0 src/vmm/src/devices/virtio/generated/virtio_net.rs | 13 ------------- src/vmm/src/devices/virtio/net/device.rs | 2 +- src/vmm/src/devices/virtio/rng/device.rs | 2 +- src/vmm/src/devices/virtio/vsock/device.rs | 3 ++- src/vmm/src/devices/virtio/vsock/mod.rs | 9 --------- tools/bindgen.sh | 13 +++++-------- 12 files changed, 15 insertions(+), 52 deletions(-) rename src/vmm/src/devices/virtio/generated/{virtio_rng.rs => virtio_config.rs} (100%) diff --git a/src/vmm/src/devices/virtio/balloon/device.rs b/src/vmm/src/devices/virtio/balloon/device.rs index 9205808a7fd..186f09275bc 100644 --- a/src/vmm/src/devices/virtio/balloon/device.rs +++ b/src/vmm/src/devices/virtio/balloon/device.rs @@ -25,7 +25,7 @@ use super::{ }; use crate::devices::virtio::balloon::BalloonError; use crate::devices::virtio::device::{IrqTrigger, IrqType}; -use crate::devices::virtio::generated::virtio_blk::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; use crate::logger::IncMetric; use crate::utils::u64_to_usize; use crate::vstate::memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap}; diff --git a/src/vmm/src/devices/virtio/block/vhost_user/device.rs b/src/vmm/src/devices/virtio/block/vhost_user/device.rs index 34948035c6b..c9907744080 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/device.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/device.rs @@ -15,9 +15,8 @@ use vmm_sys_util::eventfd::EventFd; use super::{NUM_QUEUES, QUEUE_SIZE, VhostUserBlockError}; use crate::devices::virtio::block::CacheType; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::generated::virtio_blk::{ - VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_F_VERSION_1, -}; +use crate::devices::virtio::generated::virtio_blk::{VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO}; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::vhost_user::{VhostUserHandleBackend, VhostUserHandleImpl}; diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index bb374bce5b9..e2b134a9f25 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -25,8 +25,9 @@ use crate::devices::virtio::block::CacheType; use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice}; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; use crate::devices::virtio::generated::virtio_blk::{ - VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_BLK_ID_BYTES, VIRTIO_F_VERSION_1, + VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_RO, VIRTIO_BLK_ID_BYTES, }; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; use crate::devices::virtio::generated::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use crate::devices::virtio::queue::Queue; use crate::devices::virtio::{ActivateError, TYPE_BLOCK}; diff --git a/src/vmm/src/devices/virtio/generated/mod.rs b/src/vmm/src/devices/virtio/generated/mod.rs index b96b3e4efea..ab1a73dae7d 100644 --- a/src/vmm/src/devices/virtio/generated/mod.rs +++ b/src/vmm/src/devices/virtio/generated/mod.rs @@ -11,6 +11,6 @@ #![allow(non_snake_case)] pub mod virtio_blk; +pub mod virtio_config; pub mod virtio_net; pub mod virtio_ring; -pub mod virtio_rng; diff --git a/src/vmm/src/devices/virtio/generated/virtio_blk.rs b/src/vmm/src/devices/virtio/generated/virtio_blk.rs index 635861506cf..624ef389ccd 100644 --- a/src/vmm/src/devices/virtio/generated/virtio_blk.rs +++ b/src/vmm/src/devices/virtio/generated/virtio_blk.rs @@ -15,19 +15,6 @@ unsafe_op_in_unsafe_fn )] -pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; -pub const VIRTIO_F_ANY_LAYOUT: u32 = 27; -pub const VIRTIO_F_VERSION_1: u32 = 32; -pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; -pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; -pub const VIRTIO_F_RING_PACKED: u32 = 34; -pub const VIRTIO_F_IN_ORDER: u32 = 35; -pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; -pub const VIRTIO_F_SR_IOV: u32 = 37; -pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; -pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; -pub const VIRTIO_F_RING_RESET: u32 = 40; -pub const VIRTIO_F_ADMIN_VQ: u32 = 41; pub const VIRTIO_BLK_F_SIZE_MAX: u32 = 1; pub const VIRTIO_BLK_F_SEG_MAX: u32 = 2; pub const VIRTIO_BLK_F_GEOMETRY: u32 = 4; diff --git a/src/vmm/src/devices/virtio/generated/virtio_rng.rs b/src/vmm/src/devices/virtio/generated/virtio_config.rs similarity index 100% rename from src/vmm/src/devices/virtio/generated/virtio_rng.rs rename to src/vmm/src/devices/virtio/generated/virtio_config.rs diff --git a/src/vmm/src/devices/virtio/generated/virtio_net.rs b/src/vmm/src/devices/virtio/generated/virtio_net.rs index 839cbd8b782..6d5adaac8f6 100644 --- a/src/vmm/src/devices/virtio/generated/virtio_net.rs +++ b/src/vmm/src/devices/virtio/generated/virtio_net.rs @@ -15,19 +15,6 @@ unsafe_op_in_unsafe_fn )] -pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; -pub const VIRTIO_F_ANY_LAYOUT: u32 = 27; -pub const VIRTIO_F_VERSION_1: u32 = 32; -pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; -pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; -pub const VIRTIO_F_RING_PACKED: u32 = 34; -pub const VIRTIO_F_IN_ORDER: u32 = 35; -pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; -pub const VIRTIO_F_SR_IOV: u32 = 37; -pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; -pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; -pub const VIRTIO_F_RING_RESET: u32 = 40; -pub const VIRTIO_F_ADMIN_VQ: u32 = 41; pub const VIRTIO_NET_F_CSUM: u32 = 0; pub const VIRTIO_NET_F_GUEST_CSUM: u32 = 1; pub const VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: u32 = 2; diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 38f6f7ee147..fff04d1da1a 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -16,7 +16,7 @@ use vmm_sys_util::eventfd::EventFd; use super::NET_QUEUE_MAX_SIZE; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::generated::virtio_blk::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; use crate::devices::virtio::generated::virtio_net::{ VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_UFO, diff --git a/src/vmm/src/devices/virtio/rng/device.rs b/src/vmm/src/devices/virtio/rng/device.rs index 9c9021b66d9..97ac8676e0a 100644 --- a/src/vmm/src/devices/virtio/rng/device.rs +++ b/src/vmm/src/devices/virtio/rng/device.rs @@ -13,7 +13,7 @@ use super::metrics::METRICS; use super::{RNG_NUM_QUEUES, RNG_QUEUE}; use crate::devices::DeviceError; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; -use crate::devices::virtio::generated::virtio_rng::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; use crate::devices::virtio::iov_deque::IovDequeError; use crate::devices::virtio::iovec::IoVecBufferMut; use crate::devices::virtio::queue::{FIRECRACKER_MAX_QUEUE_SIZE, Queue}; diff --git a/src/vmm/src/devices/virtio/vsock/device.rs b/src/vmm/src/devices/virtio/vsock/device.rs index 4626484ab2a..aa114f6cccb 100644 --- a/src/vmm/src/devices/virtio/vsock/device.rs +++ b/src/vmm/src/devices/virtio/vsock/device.rs @@ -31,6 +31,7 @@ use super::packet::{VSOCK_PKT_HDR_SIZE, VsockPacketRx, VsockPacketTx}; use super::{VsockBackend, defs}; use crate::devices::virtio::ActivateError; use crate::devices::virtio::device::{DeviceState, IrqTrigger, IrqType, VirtioDevice}; +use crate::devices::virtio::generated::virtio_config::{VIRTIO_F_IN_ORDER, VIRTIO_F_VERSION_1}; use crate::devices::virtio::queue::Queue as VirtQueue; use crate::devices::virtio::vsock::VsockError; use crate::devices::virtio::vsock::metrics::METRICS; @@ -49,7 +50,7 @@ pub(crate) const VIRTIO_VSOCK_EVENT_TRANSPORT_RESET: u32 = 0; /// - VIRTIO_F_IN_ORDER: the device returns used buffers in the same order that the driver makes /// them available. pub(crate) const AVAIL_FEATURES: u64 = - (1 << uapi::VIRTIO_F_VERSION_1 as u64) | (1 << uapi::VIRTIO_F_IN_ORDER as u64); + (1 << VIRTIO_F_VERSION_1 as u64) | (1 << VIRTIO_F_IN_ORDER as u64); /// Structure representing the vsock device. #[derive(Debug)] diff --git a/src/vmm/src/devices/virtio/vsock/mod.rs b/src/vmm/src/devices/virtio/vsock/mod.rs index fe338e95763..859e198860b 100644 --- a/src/vmm/src/devices/virtio/vsock/mod.rs +++ b/src/vmm/src/devices/virtio/vsock/mod.rs @@ -57,15 +57,6 @@ mod defs { pub mod uapi { - /// Virtio feature flags. - /// Defined in `/include/uapi/linux/virtio_config.h`. - /// - /// The device processes available buffers in the same order in which the device - /// offers them. - pub const VIRTIO_F_IN_ORDER: usize = 35; - /// The device conforms to the virtio spec version 1.0. - pub const VIRTIO_F_VERSION_1: u32 = 32; - /// Virtio vsock device ID. /// Defined in `include/uapi/linux/virtio_ids.h`. pub const VIRTIO_ID_VSOCK: u32 = 19; diff --git a/tools/bindgen.sh b/tools/bindgen.sh index 872b3427b67..86817a0561f 100755 --- a/tools/bindgen.sh +++ b/tools/bindgen.sh @@ -71,25 +71,22 @@ fc-bindgen \ --allowlist-var "VIRTIO_RING_F_EVENT_IDX" \ "$KERNEL_HEADERS_HOME/include/linux/virtio_ring.h" >src/vmm/src/devices/virtio/generated/virtio_ring.rs +info "BINDGEN virtio_config.h" +fc-bindgen \ + --allowlist-var "VIRTIO_F_.*" \ + "$KERNEL_HEADERS_HOME/include/linux/virtio_config.h" >src/vmm/src/devices/virtio/generated/virtio_config.rs + info "BINDGEN virtio_blk.h" fc-bindgen \ --allowlist-var "VIRTIO_BLK_.*" \ - --allowlist-var "VIRTIO_F_.*" \ "$KERNEL_HEADERS_HOME/include/linux/virtio_blk.h" >src/vmm/src/devices/virtio/generated/virtio_blk.rs info "BINDGEN virtio_net.h" fc-bindgen \ --allowlist-var "VIRTIO_NET_F_.*" \ - --allowlist-var "VIRTIO_F_.*" \ --allowlist-type "virtio_net_hdr_v1" \ "$KERNEL_HEADERS_HOME/include/linux/virtio_net.h" >src/vmm/src/devices/virtio/generated/virtio_net.rs -info "BINDGEN virtio_rng.h" -fc-bindgen \ - --allowlist-var "VIRTIO_RNG_.*" \ - --allowlist-var "VIRTIO_F_.*" \ - "$KERNEL_HEADERS_HOME/include/linux/virtio_rng.h" >src/vmm/src/devices/virtio/generated/virtio_rng.rs - info "BINDGEN prctl.h" fc-bindgen \ --allowlist-var "PR_.*" \ From c7b216f103553d03637980e844e7a8d4b2f4e4b2 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 20 Mar 2025 14:00:41 +0000 Subject: [PATCH 412/464] fix: make cargo test pass with gdb feature In CI we always run unittests without `--features gdb`, but actually with the gdb feature they dont compile. Fix this with some cfgs. Signed-off-by: Patrick Roy --- .../src/api_server/request/machine_configuration.rs | 10 ++++++++++ src/vmm/src/resources.rs | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/firecracker/src/api_server/request/machine_configuration.rs b/src/firecracker/src/api_server/request/machine_configuration.rs index 4457a9b6b75..2e8addffb74 100644 --- a/src/firecracker/src/api_server/request/machine_configuration.rs +++ b/src/firecracker/src/api_server/request/machine_configuration.rs @@ -123,6 +123,8 @@ mod tests { cpu_template: None, track_dirty_pages: Some(false), huge_pages: Some(expected), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_eq!( vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()), @@ -142,6 +144,8 @@ mod tests { cpu_template: Some(StaticCpuTemplate::None), track_dirty_pages: Some(false), huge_pages: Some(HugePageConfig::None), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_eq!( vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()), @@ -161,6 +165,8 @@ mod tests { cpu_template: None, track_dirty_pages: Some(true), huge_pages: Some(HugePageConfig::None), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_eq!( vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()), @@ -184,6 +190,8 @@ mod tests { cpu_template: Some(StaticCpuTemplate::T2), track_dirty_pages: Some(true), huge_pages: Some(HugePageConfig::None), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_eq!( vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()), @@ -209,6 +217,8 @@ mod tests { cpu_template: None, track_dirty_pages: Some(true), huge_pages: Some(HugePageConfig::None), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_eq!( vmm_action_from_request(parse_put_machine_config(&Body::new(body)).unwrap()), diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 113c24cad51..e65cc7a0121 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -1328,6 +1328,8 @@ mod tests { cpu_template: Some(StaticCpuTemplate::V1N1), track_dirty_pages: Some(false), huge_pages: Some(HugePageConfig::None), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }; assert_ne!( From ba11d476a776a8b38c56bfeb9b991678d291276f Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 15:24:11 +0000 Subject: [PATCH 413/464] refactor: de-generify fdt.rs There is absolutely no need for generics anywhere in this module, as the trait we were being generic over had only a single implementor. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/fdt.rs | 95 ++++++++++++------------------ src/vmm/src/arch/aarch64/mod.rs | 6 +- src/vmm/src/device_manager/mmio.rs | 15 ----- 3 files changed, 42 insertions(+), 74 deletions(-) diff --git a/src/vmm/src/arch/aarch64/fdt.rs b/src/vmm/src/arch/aarch64/fdt.rs index 2eb154a33b3..c708add44bf 100644 --- a/src/vmm/src/arch/aarch64/fdt.rs +++ b/src/vmm/src/arch/aarch64/fdt.rs @@ -15,6 +15,7 @@ use vm_memory::GuestMemoryError; use super::super::{DeviceType, InitrdConfig}; use super::cache_info::{CacheEntry, read_cache_config}; use super::gic::GICDevice; +use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId}; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap}; @@ -42,16 +43,6 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1; const IRQ_TYPE_EDGE_RISING: u32 = 1; const IRQ_TYPE_LEVEL_HI: u32 = 4; -/// Trait for devices to be added to the Flattened Device Tree. -pub trait DeviceInfoForFDT { - /// Returns the address where this device will be loaded. - fn addr(&self) -> u64; - /// Returns the associated interrupt for this device. - fn irq(&self) -> u32; - /// Returns the amount of memory that needs to be reserved for this device. - fn length(&self) -> u64; -} - /// Errors thrown while configuring the Flattened Device Tree for aarch64. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum FdtError { @@ -64,11 +55,11 @@ pub enum FdtError { } /// Creates the flattened device tree for this aarch64 microVM. -pub fn create_fdt( +pub fn create_fdt( guest_mem: &GuestMemoryMmap, vcpu_mpidr: Vec, cmdline: CString, - device_info: &HashMap<(DeviceType, String), T>, + device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, gic_device: &GICDevice, vmgenid: &Option, initrd: &Option, @@ -361,17 +352,18 @@ fn create_psci_node(fdt: &mut FdtWriter) -> Result<(), FdtError> { Ok(()) } -fn create_virtio_node( - fdt: &mut FdtWriter, - dev_info: &T, -) -> Result<(), FdtError> { - let virtio_mmio = fdt.begin_node(&format!("virtio_mmio@{:x}", dev_info.addr()))?; +fn create_virtio_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<(), FdtError> { + let virtio_mmio = fdt.begin_node(&format!("virtio_mmio@{:x}", dev_info.addr))?; fdt.property_string("compatible", "virtio,mmio")?; - fdt.property_array_u64("reg", &[dev_info.addr(), dev_info.length()])?; + fdt.property_array_u64("reg", &[dev_info.addr, dev_info.len])?; fdt.property_array_u32( "interrupts", - &[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING], + &[ + GIC_FDT_IRQ_TYPE_SPI, + dev_info.irq.unwrap().into(), + IRQ_TYPE_EDGE_RISING, + ], )?; fdt.property_u32("interrupt-parent", GIC_PHANDLE)?; fdt.end_node(virtio_mmio)?; @@ -379,38 +371,36 @@ fn create_virtio_node( Ok(()) } -fn create_serial_node( - fdt: &mut FdtWriter, - dev_info: &T, -) -> Result<(), FdtError> { - let serial = fdt.begin_node(&format!("uart@{:x}", dev_info.addr()))?; +fn create_serial_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<(), FdtError> { + let serial = fdt.begin_node(&format!("uart@{:x}", dev_info.addr))?; fdt.property_string("compatible", "ns16550a")?; - fdt.property_array_u64("reg", &[dev_info.addr(), dev_info.length()])?; + fdt.property_array_u64("reg", &[dev_info.addr, dev_info.len])?; fdt.property_u32("clocks", CLOCK_PHANDLE)?; fdt.property_string("clock-names", "apb_pclk")?; fdt.property_array_u32( "interrupts", - &[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING], + &[ + GIC_FDT_IRQ_TYPE_SPI, + dev_info.irq.unwrap().into(), + IRQ_TYPE_EDGE_RISING, + ], )?; fdt.end_node(serial)?; Ok(()) } -fn create_rtc_node( - fdt: &mut FdtWriter, - dev_info: &T, -) -> Result<(), FdtError> { +fn create_rtc_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<(), FdtError> { // Driver requirements: // https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/rtc/arm,pl031.yaml // We do not offer the `interrupt` property because the device // does not implement interrupt support. let compatible = b"arm,pl031\0arm,primecell\0"; - let rtc = fdt.begin_node(&format!("rtc@{:x}", dev_info.addr()))?; + let rtc = fdt.begin_node(&format!("rtc@{:x}", dev_info.addr))?; fdt.property("compatible", compatible)?; - fdt.property_array_u64("reg", &[dev_info.addr(), dev_info.length()])?; + fdt.property_array_u64("reg", &[dev_info.addr, dev_info.len])?; fdt.property_u32("clocks", CLOCK_PHANDLE)?; fdt.property_string("clock-names", "apb_pclk")?; fdt.end_node(rtc)?; @@ -418,12 +408,12 @@ fn create_rtc_node( Ok(()) } -fn create_devices_node( +fn create_devices_node( fdt: &mut FdtWriter, - dev_info: &HashMap<(DeviceType, String), T, S>, + dev_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, ) -> Result<(), FdtError> { // Create one temp Vec to store all virtio devices - let mut ordered_virtio_device: Vec<&T> = Vec::new(); + let mut ordered_virtio_device: Vec<&MMIODeviceInfo> = Vec::new(); for ((device_type, _device_id), info) in dev_info { match device_type { @@ -437,7 +427,7 @@ fn create_devices_node u64 { - self.addr - } - fn irq(&self) -> u32 { - self.irq - } - fn length(&self) -> u64 { - LEN - } - } // The `load` function from the `device_tree` will mistakenly check the actual size // of the buffer with the allocated size. This works around that. fn set_size(buf: &mut [u8], pos: usize, val: u32) { @@ -493,17 +467,26 @@ mod tests { let dev_info: HashMap<(DeviceType, std::string::String), MMIODeviceInfo> = [ ( (DeviceType::Serial, DeviceType::Serial.to_string()), - MMIODeviceInfo { addr: 0x00, irq: 1 }, + MMIODeviceInfo { + addr: 0x00, + irq: NonZeroU32::new(1), + len: LEN, + }, ), ( (DeviceType::Virtio(1), "virtio".to_string()), - MMIODeviceInfo { addr: LEN, irq: 2 }, + MMIODeviceInfo { + addr: LEN, + irq: NonZeroU32::new(2), + len: LEN, + }, ), ( (DeviceType::Rtc, "rtc".to_string()), MMIODeviceInfo { addr: 2 * LEN, - irq: 3, + irq: NonZeroU32::new(3), + len: LEN, }, ), ] diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 7ab1685cf69..a09721e1775 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -23,9 +23,9 @@ use std::fmt::Debug; use vm_memory::GuestMemoryError; -pub use self::fdt::DeviceInfoForFDT; use self::gic::GICDevice; use crate::arch::DeviceType; +use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::VmGenId; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; @@ -63,11 +63,11 @@ pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> { /// * `device_info` - A hashmap containing the attached devices for building FDT device nodes. /// * `gic_device` - The GIC device. /// * `initrd` - Information about an optional initrd. -pub fn configure_system( +pub fn configure_system( guest_mem: &GuestMemoryMmap, cmdline_cstring: CString, vcpu_mpidr: Vec, - device_info: &HashMap<(DeviceType, String), T>, + device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, gic_device: &GICDevice, vmgenid: &Option, initrd: &Option, diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index b4961623a15..20d9b381e1c 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -23,8 +23,6 @@ use vm_allocator::AllocPolicy; use super::resources::ResourceAllocator; use crate::arch::DeviceType; use crate::arch::DeviceType::Virtio; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::DeviceInfoForFDT; use crate::devices::BusDevice; #[cfg(target_arch = "aarch64")] use crate::devices::legacy::RTCDevice; @@ -522,19 +520,6 @@ impl MMIODeviceManager { } } -#[cfg(target_arch = "aarch64")] -impl DeviceInfoForFDT for MMIODeviceInfo { - fn addr(&self) -> u64 { - self.addr - } - fn irq(&self) -> u32 { - self.irq.unwrap().into() - } - fn length(&self) -> u64 { - self.len - } -} - #[cfg(test)] mod tests { From ff8ca9300f180808f016ffee617339ed802c6487 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 16:49:17 +0000 Subject: [PATCH 414/464] refactor: do not redefine x86 constant in test_vsock_bof This test is all about testing what happens when a vsock driver places virtio buffers close to / around the MMIO gap on x86_64 systems. Since this test thus doesn't really serve a purpose on aarch64, we can just cfg(target_arch = "x86_64") it, and reuse the constants from arch::x86_64 instead of redefining them again. fwiw, I have no idea what "bof" means. I'm also confused by this test passing on ARM in the first place, given that some of the comments indicate to me that it should fail if the buffers overlap the mmio gap (which doesn't exist on arm, so nothing should fail?). Signed-off-by: Patrick Roy --- src/vmm/src/arch/x86_64/mod.rs | 3 +- .../src/devices/virtio/vsock/event_handler.rs | 40 +++++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 24a7de7ec8a..9c3c2b11ce3 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -73,7 +73,8 @@ pub enum ConfigurationError { StartInfoSetup, } -const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32; +/// First address that cannot be addressed using 32 bit anymore. +pub const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32; /// Size of MMIO gap at top of 32-bit address space. pub const MEM_32BIT_GAP_SIZE: u64 = 768 << 20; diff --git a/src/vmm/src/devices/virtio/vsock/event_handler.rs b/src/vmm/src/devices/virtio/vsock/event_handler.rs index a16cff7dbfc..2dab8490119 100755 --- a/src/vmm/src/devices/virtio/vsock/event_handler.rs +++ b/src/vmm/src/devices/virtio/vsock/event_handler.rs @@ -223,10 +223,7 @@ mod tests { use super::super::*; use super::*; - use crate::devices::virtio::vsock::packet::VSOCK_PKT_HDR_SIZE; use crate::devices::virtio::vsock::test_utils::{EventHandlerContext, TestContext}; - use crate::test_utils::multi_region_mem; - use crate::vstate::memory::Bytes; #[test] fn test_txq_event() { @@ -427,8 +424,9 @@ mod tests { // function for testing error cases, so the asserts always expect is_err() to be true. When // desc_idx = 0 we are altering the header (first descriptor in the chain), and when // desc_idx = 1 we are altering the packet buffer. + #[cfg(target_arch = "x86_64")] fn vsock_bof_helper(test_ctx: &mut TestContext, desc_idx: usize, addr: u64, len: u32) { - use crate::vstate::memory::GuestAddress; + use crate::vstate::memory::{Bytes, GuestAddress}; assert!(desc_idx <= 1); @@ -472,19 +470,22 @@ mod tests { } #[test] + #[cfg(target_arch = "x86_64")] + #[allow(clippy::cast_possible_truncation)] /* casting of constants we know fit into u32 */ fn test_vsock_bof() { + use crate::arch::MMIO_MEM_START; + use crate::arch::x86_64::{FIRST_ADDR_PAST_32BITS, MEM_32BIT_GAP_SIZE}; + use crate::devices::virtio::vsock::packet::VSOCK_PKT_HDR_SIZE; + use crate::test_utils::multi_region_mem; use crate::vstate::memory::GuestAddress; - const GAP_SIZE: u32 = 768 << 20; - const FIRST_AFTER_GAP: usize = 1 << 32; - const GAP_START_ADDR: usize = FIRST_AFTER_GAP - GAP_SIZE as usize; const MIB: usize = 1 << 20; let mut test_ctx = TestContext::new(); test_ctx.mem = multi_region_mem(&[ (GuestAddress(0), 8 * MIB), - (GuestAddress((GAP_START_ADDR - MIB) as u64), MIB), - (GuestAddress(FIRST_AFTER_GAP as u64), MIB), + (GuestAddress(MMIO_MEM_START - MIB as u64), MIB), + (GuestAddress(FIRST_ADDR_PAST_32BITS), MIB), ]); // The default configured descriptor chains are valid. @@ -506,20 +507,25 @@ mod tests { } // Let's check what happens when the header descriptor is right before the gap. - vsock_bof_helper( - &mut test_ctx, - 0, - GAP_START_ADDR as u64 - 1, - VSOCK_PKT_HDR_SIZE, - ); + vsock_bof_helper(&mut test_ctx, 0, MMIO_MEM_START - 1, VSOCK_PKT_HDR_SIZE); // Let's check what happens when the buffer descriptor crosses into the gap, but does // not go past its right edge. - vsock_bof_helper(&mut test_ctx, 1, GAP_START_ADDR as u64 - 4, GAP_SIZE + 4); + vsock_bof_helper( + &mut test_ctx, + 1, + MMIO_MEM_START - 4, + MEM_32BIT_GAP_SIZE as u32 + 4, + ); // Let's modify the buffer descriptor addr and len such that it crosses over the MMIO gap, // and check we cannot assemble the VsockPkts. - vsock_bof_helper(&mut test_ctx, 1, GAP_START_ADDR as u64 - 4, GAP_SIZE + 100); + vsock_bof_helper( + &mut test_ctx, + 1, + MMIO_MEM_START - 4, + MEM_32BIT_GAP_SIZE as u32 + 100, + ); } #[test] From 76f1527a717c806bc9f3384963c68d7140fc99e1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 17:24:43 +0000 Subject: [PATCH 415/464] refactor: introduce mib_to_bytes helper Left-shifting by 20 to convert MiB to bytes is ubiquitous in our codebase, but probably somewhat arcane to people not familiar with low level stuff. Let's define a helper for the conversion. Signed-off-by: Patrick Roy --- src/vmm/src/arch/x86_64/mod.rs | 10 +++++----- src/vmm/src/builder.rs | 3 ++- src/vmm/src/devices/virtio/vsock/event_handler.rs | 3 ++- src/vmm/src/resources.rs | 4 +++- src/vmm/src/utils/mod.rs | 8 ++++++++ src/vmm/src/vstate/memory.rs | 8 ++++---- src/vmm/src/vstate/vcpu.rs | 3 ++- src/vmm/src/vstate/vm.rs | 3 ++- 8 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 9c3c2b11ce3..ad680d89cff 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -41,7 +41,7 @@ use linux_loader::loader::elf::start_info::{ use crate::arch::{BootProtocol, InitrdConfig, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::device_manager::resources::ResourceAllocator; -use crate::utils::u64_to_usize; +use crate::utils::{mib_to_bytes, u64_to_usize}; use crate::vstate::memory::{ Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, }; @@ -77,7 +77,7 @@ pub enum ConfigurationError { pub const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32; /// Size of MMIO gap at top of 32-bit address space. -pub const MEM_32BIT_GAP_SIZE: u64 = 768 << 20; +pub const MEM_32BIT_GAP_SIZE: u64 = mib_to_bytes(768) as u64; /// The start of the memory area reserved for MMIO devices. pub const MMIO_MEM_START: u64 = FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE; /// The size of the memory area reserved for MMIO devices. @@ -403,7 +403,7 @@ mod tests { ); // Now assigning some memory that falls before the 32bit memory hole. - let mem_size = 128 << 20; + let mem_size = mib_to_bytes(128); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); configure_system( @@ -428,7 +428,7 @@ mod tests { .unwrap(); // Now assigning some memory that is equal to the start of the 32bit memory hole. - let mem_size = 3328 << 20; + let mem_size = mib_to_bytes(3328); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); configure_system( @@ -453,7 +453,7 @@ mod tests { .unwrap(); // Now assigning some memory that falls after the 32bit memory hole. - let mem_size = 3330 << 20; + let mem_size = mib_to_bytes(3330); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); configure_system( diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index ae9cab9e51c..d21ed0ca40e 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -1050,6 +1050,7 @@ pub(crate) mod tests { use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; use crate::test_utils::{single_region_mem, single_region_mem_at}; + use crate::utils::mib_to_bytes; use crate::vmm_config::balloon::{BALLOON_DEV_ID, BalloonBuilder, BalloonDeviceConfig}; use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE; use crate::vmm_config::drive::{BlockBuilder, BlockDeviceConfig}; @@ -1113,7 +1114,7 @@ pub(crate) mod tests { } pub(crate) fn default_vmm() -> Vmm { - let (kvm, mut vm, guest_memory) = setup_vm_with_memory(128 << 20); + let (kvm, mut vm, guest_memory) = setup_vm_with_memory(mib_to_bytes(128)); let mmio_device_manager = MMIODeviceManager::new(); let acpi_device_manager = ACPIDeviceManager::new(); diff --git a/src/vmm/src/devices/virtio/vsock/event_handler.rs b/src/vmm/src/devices/virtio/vsock/event_handler.rs index 2dab8490119..632148546e5 100755 --- a/src/vmm/src/devices/virtio/vsock/event_handler.rs +++ b/src/vmm/src/devices/virtio/vsock/event_handler.rs @@ -477,9 +477,10 @@ mod tests { use crate::arch::x86_64::{FIRST_ADDR_PAST_32BITS, MEM_32BIT_GAP_SIZE}; use crate::devices::virtio::vsock::packet::VSOCK_PKT_HDR_SIZE; use crate::test_utils::multi_region_mem; + use crate::utils::mib_to_bytes; use crate::vstate::memory::GuestAddress; - const MIB: usize = 1 << 20; + const MIB: usize = mib_to_bytes(1); let mut test_ctx = TestContext::new(); test_ctx.mem = multi_region_mem(&[ diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index e65cc7a0121..2d472a3f3e2 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -13,6 +13,7 @@ use crate::logger::info; use crate::mmds; use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; +use crate::utils::mib_to_bytes; use crate::utils::net::ipv4addr::is_link_local_valid; use crate::vmm_config::balloon::*; use crate::vmm_config::boot_source::{ @@ -462,7 +463,8 @@ impl VmResources { self.machine_config.huge_pages, ) } else { - let regions = crate::arch::arch_memory_regions(self.machine_config.mem_size_mib << 20); + let regions = + crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib)); GuestMemoryMmap::anonymous( regions.into_iter(), self.machine_config.track_dirty_pages, diff --git a/src/vmm/src/utils/mod.rs b/src/vmm/src/utils/mod.rs index a0ee2e90b6b..9c81c7a3016 100644 --- a/src/vmm/src/utils/mod.rs +++ b/src/vmm/src/utils/mod.rs @@ -13,6 +13,9 @@ pub mod sm; use std::num::Wrapping; use std::result::Result; +/// How many bits to left-shift by to convert MiB to bytes +const MIB_TO_BYTES_SHIFT: usize = 20; + /// Return the default page size of the platform, in bytes. pub fn get_page_size() -> Result { // SAFETY: Safe because the parameters are valid. @@ -45,3 +48,8 @@ pub const fn usize_to_u64(num: usize) -> u64 { pub const fn wrap_usize_to_u32(num: usize) -> Wrapping { Wrapping(((num as u64) & 0xFFFFFFFF) as u32) } + +/// Converts MiB to Bytes +pub const fn mib_to_bytes(mib: usize) -> usize { + mib << MIB_TO_BYTES_SHIFT +} diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index e0f47848684..8875791f3a6 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -23,7 +23,7 @@ use vmm_sys_util::errno; use crate::DirtyBitmap; use crate::arch::arch_memory_regions; -use crate::utils::{get_page_size, u64_to_usize}; +use crate::utils::{get_page_size, mib_to_bytes, u64_to_usize}; use crate::vmm_config::machine_config::HugePageConfig; /// Type of GuestMemoryMmap. @@ -72,7 +72,7 @@ where huge_pages: HugePageConfig, ) -> Result { let memfd_file = create_memfd(mem_size_mib, huge_pages.into())?.into_file(); - let regions = arch_memory_regions(mem_size_mib << 20).into_iter(); + let regions = arch_memory_regions(mib_to_bytes(mem_size_mib)).into_iter(); Self::create( regions, @@ -330,7 +330,7 @@ fn create_memfd( size: usize, hugetlb_size: Option, ) -> Result { - let mem_size = size << 20; + let mem_size = mib_to_bytes(size); // Create a memfd. let opts = memfd::MemfdOptions::default() .hugetlb(hugetlb_size) @@ -713,7 +713,7 @@ mod tests { #[test] fn test_create_memfd() { let size = 1; - let size_mb = 1 << 20; + let size_mb = mib_to_bytes(1) as u64; let memfd = create_memfd(size, None).unwrap(); diff --git a/src/vmm/src/vstate/vcpu.rs b/src/vmm/src/vstate/vcpu.rs index d54d7de759b..b7de0017e46 100644 --- a/src/vmm/src/vstate/vcpu.rs +++ b/src/vmm/src/vstate/vcpu.rs @@ -775,6 +775,7 @@ pub(crate) mod tests { use crate::devices::BusDevice; use crate::devices::bus::DummyDevice; use crate::seccomp::get_empty_filters; + use crate::utils::mib_to_bytes; use crate::utils::signal::validate_signal_num; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; @@ -962,7 +963,7 @@ pub(crate) mod tests { fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd, GuestMemoryMmap) { Vcpu::register_kick_signal_handler(); // Need enough mem to boot linux. - let mem_size = 64 << 20; + let mem_size = mib_to_bytes(64); let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(mem_size); let vcpu_exit_evt = vcpu.exit_evt.try_clone().unwrap(); diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 4292c2f2f49..bb13b17ee99 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -135,6 +135,7 @@ impl Vm { pub(crate) mod tests { use super::*; use crate::test_utils::single_region_mem; + use crate::utils::mib_to_bytes; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; @@ -189,7 +190,7 @@ pub(crate) mod tests { #[test] fn test_create_vcpus() { let vcpu_count = 2; - let (_, mut vm, _) = setup_vm_with_memory(128 << 20); + let (_, mut vm, _) = setup_vm_with_memory(mib_to_bytes(128)); let (vcpu_vec, _) = vm.create_vcpus(vcpu_count).unwrap(); From 4181e982a31fe7bdd72fc10e7b0c43e58b0c47cc Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 10:30:05 +0000 Subject: [PATCH 416/464] refactor: drop pointless .map() calls The return value here was ignored anyway, so no need to map the unit () to VmmData::Empty. Signed-off-by: Patrick Roy --- src/vmm/src/rpc_interface.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 8eb7227347a..127b75e594e 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -808,14 +808,12 @@ impl RuntimeApiController { // vhost-user-block updates if new_cfg.path_on_host.is_none() && new_cfg.rate_limiter.is_none() { vmm.update_vhost_user_block_config(&new_cfg.drive_id) - .map(|()| VmmData::Empty) .map_err(DriveError::DeviceUpdate)?; } // virtio-block updates if let Some(new_path) = new_cfg.path_on_host { vmm.update_block_device_path(&new_cfg.drive_id, new_path) - .map(|()| VmmData::Empty) .map_err(DriveError::DeviceUpdate)?; } if new_cfg.rate_limiter.is_some() { @@ -824,7 +822,6 @@ impl RuntimeApiController { RateLimiterUpdate::from(new_cfg.rate_limiter).bandwidth, RateLimiterUpdate::from(new_cfg.rate_limiter).ops, ) - .map(|()| VmmData::Empty) .map_err(DriveError::DeviceUpdate)?; } Ok(VmmData::Empty) From c52f1a771f6f6dac99f061854578309503fcd29a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 10:40:12 +0000 Subject: [PATCH 417/464] refactor: move StartMicrovmError::AllocateResources into VmmError This means that `create_vmm_and_vcpus` now does not use any variants of `StartMicrovmError` directly, and as a next step can be converted to return `VmmError` directly, which will eliminate all the `map_err` inside. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 6 +++--- src/vmm/src/lib.rs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index d21ed0ca40e..fc9da4b996b 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -130,8 +130,6 @@ pub enum StartMicrovmError { SetVmResources(MachineConfigError), /// Cannot create the entropy device: {0} CreateEntropyDevice(crate::devices::virtio::rng::EntropyError), - /// Failed to allocate guest resource: {0} - AllocateResources(#[from] vm_allocator::Error), /// Error configuring ACPI: {0} #[cfg(target_arch = "x86_64")] Acpi(#[from] crate::acpi::AcpiError), @@ -177,7 +175,9 @@ fn create_vmm_and_vcpus( .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; - let resource_allocator = ResourceAllocator::new()?; + let resource_allocator = ResourceAllocator::new() + .map_err(VmmError::AllocateResources) + .map_err(StartMicrovmError::Internal)?; // Instantiate the MMIO device manager. let mmio_device_manager = MMIODeviceManager::new(); diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 492077df068..4908731c4f7 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -205,6 +205,8 @@ pub const HTTP_MAX_PAYLOAD_SIZE: usize = 51200; /// have permissions to open the KVM fd). #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum VmmError { + /// Failed to allocate guest resource: {0} + AllocateResources(#[from] vm_allocator::Error), #[cfg(target_arch = "aarch64")] /// Invalid command line error. Cmdline, From 5bc902b83eb313044e6d46e2048a4ae1f144bdf5 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 10:43:38 +0000 Subject: [PATCH 418/464] refactor: Have create_vmm_and_vcpus return VmmError Eliminate a lot of .map_err(Internal) to make the code more readable. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 44 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index fc9da4b996b..e7472801b77 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -32,6 +32,7 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] use crate::acpi; use crate::arch::{BootProtocol, EntryPoint, InitrdConfig}; +use crate::builder::StartMicrovmError::Internal; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; use crate::cpu_config::templates::{ @@ -157,27 +158,15 @@ fn create_vmm_and_vcpus( uffd: Option, vcpu_count: u8, kvm_capabilities: Vec, -) -> Result<(Vmm, Vec), StartMicrovmError> { - use self::StartMicrovmError::*; - - let kvm = Kvm::new(kvm_capabilities) - .map_err(VmmError::Kvm) - .map_err(StartMicrovmError::Internal)?; +) -> Result<(Vmm, Vec), VmmError> { + let kvm = Kvm::new(kvm_capabilities).map_err(VmmError::Kvm)?; // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. - let mut vm = Vm::new(&kvm) - .map_err(VmmError::Vm) - .map_err(StartMicrovmError::Internal)?; - kvm.check_memory(&guest_memory) - .map_err(VmmError::Kvm) - .map_err(StartMicrovmError::Internal)?; - vm.memory_init(&guest_memory) - .map_err(VmmError::Vm) - .map_err(StartMicrovmError::Internal)?; + let mut vm = Vm::new(&kvm).map_err(VmmError::Vm)?; + kvm.check_memory(&guest_memory).map_err(VmmError::Kvm)?; + vm.memory_init(&guest_memory).map_err(VmmError::Vm)?; - let resource_allocator = ResourceAllocator::new() - .map_err(VmmError::AllocateResources) - .map_err(StartMicrovmError::Internal)?; + let resource_allocator = ResourceAllocator::new().map_err(VmmError::AllocateResources)?; // Instantiate the MMIO device manager. let mmio_device_manager = MMIODeviceManager::new(); @@ -185,10 +174,7 @@ fn create_vmm_and_vcpus( // Instantiate ACPI device manager. let acpi_device_manager = ACPIDeviceManager::new(); - let (vcpus, vcpus_exit_evt) = vm - .create_vcpus(vcpu_count) - .map_err(VmmError::Vm) - .map_err(Internal)?; + let (vcpus, vcpus_exit_evt) = vm.create_vcpus(vcpu_count).map_err(VmmError::Vm)?; #[cfg(target_arch = "x86_64")] let pio_device_manager = { @@ -196,14 +182,10 @@ fn create_vmm_and_vcpus( set_stdout_nonblocking(); // Serial device setup. - let serial_device = - setup_serial_device(event_manager, std::io::stdin(), io::stdout()).map_err(Internal)?; + let serial_device = setup_serial_device(event_manager, std::io::stdin(), io::stdout())?; // x86_64 uses the i8042 reset event as the Vmm exit event. - let reset_evt = vcpus_exit_evt - .try_clone() - .map_err(VmmError::EventFd) - .map_err(Internal)?; + let reset_evt = vcpus_exit_evt.try_clone().map_err(VmmError::EventFd)?; // create pio dev manager with legacy devices // TODO Remove these unwraps. @@ -276,7 +258,8 @@ pub fn build_microvm_for_boot( None, vm_resources.machine_config.vcpu_count, cpu_template.kvm_capabilities.clone(), - )?; + ) + .map_err(Internal)?; #[cfg(feature = "gdb")] let (gdb_tx, gdb_rx) = mpsc::channel(); @@ -471,7 +454,8 @@ pub fn build_microvm_from_snapshot( uffd, vm_resources.machine_config.vcpu_count, microvm_state.kvm_state.kvm_cap_modifiers.clone(), - )?; + ) + .map_err(Internal)?; #[cfg(target_arch = "x86_64")] { From 83f77b35d2d915b9f98fb6fc02707d197e297cce Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 10:46:17 +0000 Subject: [PATCH 419/464] refactor: use #[from] in VmmError When a variant wraps another error type, and this error type does not appear in any other variant, use thiserrors #[from] directive to implement a `From` impl. This allows eliminating almost all remaining `map_err`s from `create_vmm_and_vcpus`, as the `?` operator will automatically call .from() once (although it cannot do it for multiple layers of wrapping, which is why it was important to change the function to return VmmError). Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 12 ++++++------ src/vmm/src/lib.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index e7472801b77..f8d51b69573 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -159,14 +159,14 @@ fn create_vmm_and_vcpus( vcpu_count: u8, kvm_capabilities: Vec, ) -> Result<(Vmm, Vec), VmmError> { - let kvm = Kvm::new(kvm_capabilities).map_err(VmmError::Kvm)?; + let kvm = Kvm::new(kvm_capabilities)?; // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. - let mut vm = Vm::new(&kvm).map_err(VmmError::Vm)?; - kvm.check_memory(&guest_memory).map_err(VmmError::Kvm)?; - vm.memory_init(&guest_memory).map_err(VmmError::Vm)?; + let mut vm = Vm::new(&kvm)?; + kvm.check_memory(&guest_memory)?; + vm.memory_init(&guest_memory)?; - let resource_allocator = ResourceAllocator::new().map_err(VmmError::AllocateResources)?; + let resource_allocator = ResourceAllocator::new()?; // Instantiate the MMIO device manager. let mmio_device_manager = MMIODeviceManager::new(); @@ -174,7 +174,7 @@ fn create_vmm_and_vcpus( // Instantiate ACPI device manager. let acpi_device_manager = ACPIDeviceManager::new(); - let (vcpus, vcpus_exit_evt) = vm.create_vcpus(vcpu_count).map_err(VmmError::Vm)?; + let (vcpus, vcpus_exit_evt) = vm.create_vcpus(vcpu_count)?; #[cfg(target_arch = "x86_64")] let pio_device_manager = { diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 4908731c4f7..993409dc819 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -257,9 +257,9 @@ pub enum VmmError { /// Cannot spawn Vcpu thread: {0} VcpuSpawn(io::Error), /// Vm error: {0} - Vm(vstate::vm::VmError), + Vm(#[from] vstate::vm::VmError), /// Kvm error: {0} - Kvm(vstate::kvm::KvmError), + Kvm(#[from] vstate::kvm::KvmError), /// Error thrown by observer object on Vmm initialization: {0} VmmObserverInit(vmm_sys_util::errno::Error), /// Error thrown by observer object on Vmm teardown: {0} From 99b7e2ca8be4e7fd54657b8a67f078d7e478844b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 24 Mar 2025 10:53:09 +0000 Subject: [PATCH 420/464] refactor: impl From for StartMicrovmError This allows us to eliminate some more .map_err(Internal). Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index f8d51b69573..cd1e063fb40 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -104,7 +104,7 @@ pub enum StartMicrovmError { /// Cannot load initrd due to an invalid image: {0} InitrdRead(io::Error), /// Internal error while starting microVM: {0} - Internal(VmmError), + Internal(#[from] VmmError), /// Failed to get CPU template: {0} GetCpuTemplate(#[from] GetCpuTemplateError), /// Invalid kernel command line: {0} @@ -258,8 +258,7 @@ pub fn build_microvm_for_boot( None, vm_resources.machine_config.vcpu_count, cpu_template.kvm_capabilities.clone(), - ) - .map_err(Internal)?; + )?; #[cfg(feature = "gdb")] let (gdb_tx, gdb_rx) = mpsc::channel(); @@ -306,7 +305,7 @@ pub fn build_microvm_for_boot( } #[cfg(target_arch = "aarch64")] - attach_legacy_devices_aarch64(event_manager, &mut vmm, &mut boot_cmdline).map_err(Internal)?; + attach_legacy_devices_aarch64(event_manager, &mut vmm, &mut boot_cmdline)?; attach_vmgenid_device(&mut vmm)?; @@ -346,8 +345,7 @@ pub fn build_microvm_for_boot( .ok_or_else(|| MissingSeccompFilters("vcpu".to_string()))? .clone(), ) - .map_err(VmmError::VcpuStart) - .map_err(Internal)?; + .map_err(VmmError::VcpuStart)?; // Load seccomp filters for the VMM thread. // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters @@ -358,8 +356,7 @@ pub fn build_microvm_for_boot( .get("vmm") .ok_or_else(|| MissingSeccompFilters("vmm".to_string()))?, ) - .map_err(VmmError::SeccompFilters) - .map_err(Internal)?; + .map_err(VmmError::SeccompFilters)?; event_manager.add_subscriber(vmm.clone()); @@ -384,10 +381,7 @@ pub fn build_and_boot_microvm( debug!("event_end: build microvm for boot"); // The vcpus start off in the `Paused` state, let them run. debug!("event_start: boot microvm"); - vmm.lock() - .unwrap() - .resume_vm() - .map_err(StartMicrovmError::Internal)?; + vmm.lock().unwrap().resume_vm()?; debug!("event_end: boot microvm"); Ok(vmm) } @@ -559,7 +553,7 @@ fn load_kernel( let mut kernel_file = boot_config .kernel_file .try_clone() - .map_err(|err| StartMicrovmError::Internal(VmmError::KernelFile(err)))?; + .map_err(VmmError::KernelFile)?; let entry_addr = Loader::load::( guest_memory, @@ -593,7 +587,7 @@ fn load_kernel( let mut kernel_file = boot_config .kernel_file .try_clone() - .map_err(|err| StartMicrovmError::Internal(VmmError::KernelFile(err)))?; + .map_err(VmmError::KernelFile)?; let entry_addr = Loader::load::( guest_memory, @@ -762,8 +756,7 @@ pub fn configure_system_for_boot( for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu .init(&cpu_template.vcpu_features) - .map_err(VmmError::VcpuInit) - .map_err(Internal)?; + .map_err(VmmError::VcpuInit)?; } let mut regs = Aarch64RegisterVec::default(); @@ -787,8 +780,7 @@ pub fn configure_system_for_boot( for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu .configure(vmm.guest_memory(), entry_point, &vcpu_config) - .map_err(VmmError::VcpuConfigure) - .map_err(Internal)?; + .map_err(VmmError::VcpuConfigure)?; } // Write the kernel command line to guest memory. This is x86_64 specific, since on @@ -836,8 +828,7 @@ pub fn configure_system_for_boot( &vcpu_config, &optional_capabilities, ) - .map_err(VmmError::VcpuConfigure) - .map_err(Internal)?; + .map_err(VmmError::VcpuConfigure)?; } let vcpu_mpidr = vcpus .iter_mut() From cf9e48ef4967781db834a6c2c7021bd8ab172bae Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Mon, 24 Mar 2025 15:33:39 +0000 Subject: [PATCH 421/464] test(api): exclude /snapshot/load from duration check When restoring from snapshot via UFFD, if the UFFD handler is eager enough (eg like the fault-all handler we use for testing), memory population for a sufficiently large VM may take longer than the limit we have. Signed-off-by: Nikita Kalyazin --- tests/framework/microvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index d3a5fdceaf9..45375cd9c61 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -390,7 +390,7 @@ def _validate_api_response_times(self): "Got API call duration log entry before request entry" ) - if current_call.url != "/snapshot/create": + if current_call.url not in ["/snapshot/create", "/snapshot/load"]: exec_time = float(match.group("execution_time")) / 1000.0 assert ( From 56729e7799f265fbc7bc1913a606176c3a5b76f9 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Mon, 24 Mar 2025 15:35:37 +0000 Subject: [PATCH 422/464] test(devtool): sextuple number of preallocated huge pages With current number of huge pages (4096) being ok for 1GiB VMs, we need 6 times more of them for 6GiB VMs. Signed-off-by: Nikita Kalyazin --- tools/devtool | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/devtool b/tools/devtool index 44f10657c06..57637a553cc 100755 --- a/tools/devtool +++ b/tools/devtool @@ -743,9 +743,9 @@ cmd_test() { # It seems that even if the tests using huge pages run sequentially on ag=1 agents, right-sizing the huge pages # pool to the total number of huge pages used across all tests results in spurious failures with pool depletion # anyway (something else on the host seems to be stealing our huge pages, and we cannot "ear mark" them for - # Firecracker processes). Thus, just allocate 8GB of them and call it a day. + # Firecracker processes). Thus, just allocate 48GB of them and call it a day. say "Setting up huge pages pool" - num_hugetlbfs_pages=4096 + num_hugetlbfs_pages=24552 huge_pages_old=$(cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) huge_pages_new=$(echo $num_hugetlbfs_pages |sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) From a6c9559ea72ef50663c15fcc4370d1d2f0ba6d74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 17:06:57 +0000 Subject: [PATCH 423/464] build(deps): Bump the firecracker group with 13 updates Bumps the firecracker group with 13 updates: | Package | From | To | | --- | --- | --- | | [zerocopy](https://github.com/google/zerocopy) | `0.8.23` | `0.8.24` | | [uuid](https://github.com/uuid-rs/uuid) | `1.15.1` | `1.16.0` | | [log](https://github.com/rust-lang/log) | `0.4.26` | `0.4.27` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.13.3` | `0.13.4` | | [aws-lc-sys](https://github.com/aws/aws-lc-rs) | `0.27.0` | `0.27.1` | | [cc](https://github.com/rust-lang/cc-rs) | `1.2.16` | `1.2.17` | | [half](https://github.com/starkat99/half-rs) | `2.4.1` | `2.5.0` | | [jiff](https://github.com/BurntSushi/jiff) | `0.2.4` | `0.2.5` | | [jiff-static](https://github.com/BurntSushi/jiff) | `0.2.4` | `0.2.5` | | [once_cell](https://github.com/matklad/once_cell) | `1.21.0` | `1.21.1` | | [prettyplease](https://github.com/dtolnay/prettyplease) | `0.2.30` | `0.2.31` | | [uuid-macro-internal](https://github.com/uuid-rs/uuid) | `1.15.1` | `1.16.0` | | [winnow](https://github.com/winnow-rs/winnow) | `0.7.3` | `0.7.4` | Updates `zerocopy` from 0.8.23 to 0.8.24 - [Release notes](https://github.com/google/zerocopy/releases) - [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md) - [Commits](https://github.com/google/zerocopy/compare/v0.8.23...v0.8.24) Updates `uuid` from 1.15.1 to 1.16.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/v1.15.1...v1.16.0) Updates `log` from 0.4.26 to 0.4.27 - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27) Updates `aws-lc-fips-sys` from 0.13.3 to 0.13.4 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.3...aws-lc-fips-sys/v0.13.4) Updates `aws-lc-sys` from 0.27.0 to 0.27.1 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.27.0...aws-lc-sys/v0.27.1) Updates `cc` from 1.2.16 to 1.2.17 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.16...cc-v1.2.17) Updates `half` from 2.4.1 to 2.5.0 - [Release notes](https://github.com/starkat99/half-rs/releases) - [Changelog](https://github.com/VoidStarKat/half-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/starkat99/half-rs/compare/v2.4.1...v2.5.0) Updates `jiff` from 0.2.4 to 0.2.5 - [Release notes](https://github.com/BurntSushi/jiff/releases) - [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md) - [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.4...jiff-static-0.2.5) Updates `jiff-static` from 0.2.4 to 0.2.5 - [Release notes](https://github.com/BurntSushi/jiff/releases) - [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md) - [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.4...jiff-static-0.2.5) Updates `once_cell` from 1.21.0 to 1.21.1 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.21.0...v1.21.1) Updates `prettyplease` from 0.2.30 to 0.2.31 - [Release notes](https://github.com/dtolnay/prettyplease/releases) - [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.30...0.2.31) Updates `uuid-macro-internal` from 1.15.1 to 1.16.0 - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/v1.15.1...v1.16.0) Updates `winnow` from 0.7.3 to 0.7.4 - [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md) - [Commits](https://github.com/winnow-rs/winnow/compare/v0.7.3...v0.7.4) --- updated-dependencies: - dependency-name: zerocopy dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: half dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: jiff dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: jiff-static dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: once_cell dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: prettyplease dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: uuid-macro-internal dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: winnow dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 71 +++++++++++++++++------------------ src/acpi-tables/Cargo.toml | 2 +- src/clippy-tracing/Cargo.toml | 2 +- src/log-instrument/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/vmm/Cargo.toml | 4 +- 6 files changed, 41 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54753c8a76d..daeb0822782 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "displaydoc", "thiserror 2.0.12", "vm-memory", - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -126,16 +126,15 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29003a681b2b9465c1139bfb726da452a841a8b025f35953f3bce71139f10b21" +checksum = "7c6f97c07b7eb57063d9f62cbb5638bcdf699888f8e9febd07a88b156c4b05bb" dependencies = [ "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", - "paste", "regex", ] @@ -153,9 +152,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbe221bbf523b625a4dd8585c7f38166e31167ec2ca98051dbcb4c3b6e825d2" +checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" dependencies = [ "bindgen 0.69.5", "cc", @@ -258,9 +257,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -699,9 +698,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "half" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" dependencies = [ "cfg-if", "crunchy", @@ -808,9 +807,9 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" dependencies = [ "jiff-static", "log", @@ -821,9 +820,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" dependencies = [ "proc-macro2", "quote", @@ -907,9 +906,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "serde", ] @@ -1000,9 +999,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.0" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "oorandom" @@ -1061,14 +1060,14 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] name = "prettyplease" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" dependencies = [ "proc-macro2", "syn", @@ -1127,7 +1126,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.0", - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -1166,7 +1165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -1264,7 +1263,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.12", - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -1547,9 +1546,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.15.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ "getrandom 0.3.1", "rand 0.9.0", @@ -1558,9 +1557,9 @@ dependencies = [ [[package]] name = "uuid-macro-internal" -version = "1.15.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9521621447c21497fac206ffe6e9f642f977c4f82eeba9201055f64884d9cb01" +checksum = "72dcd78c4f979627a754f5522cea6e6a25e55139056535fe6e69c506cd64a862" dependencies = [ "proc-macro2", "quote", @@ -1662,7 +1661,7 @@ dependencies = [ "vm-memory", "vm-superio", "vmm-sys-util", - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -1820,9 +1819,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" dependencies = [ "memchr", ] @@ -1848,11 +1847,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive 0.8.24", ] [[package]] @@ -1868,9 +1867,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index d98e8b93ded..141f09a47da 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" displaydoc = "0.2.5" thiserror = "2.0.12" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.23", features = ["derive"] } +zerocopy = { version = "0.8.24", features = ["derive"] } [lib] bench = false diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index 60bce291e42..b3ecacfc49d 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -18,7 +18,7 @@ syn = { version = "2.0.100", features = ["full", "extra-traits", "visit", "visit walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.15.1", features = ["v4"] } +uuid = { version = "1.16.0", features = ["v4"] } [lints] workspace = true diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index d42b1a7a4dc..39ae2ef6967 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -28,7 +28,7 @@ name = "five" name = "six" [dependencies] -log = "0.4.26" +log = "0.4.27" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index f183573d84d..09472f8b45e 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -23,7 +23,7 @@ libc = "0.2.171" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" thiserror = "2.0.12" -zerocopy = { version = "0.8.23" } +zerocopy = { version = "0.8.24" } [lints] workspace = true diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 34e35e2a4ef..1b941b86416 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -26,7 +26,7 @@ kvm-bindings = { version = "0.11.1", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.21.0" libc = "0.2.171" linux-loader = "0.13.0" -log = { version = "0.4.26", features = ["std", "serde"] } +log = { version = "0.4.27", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } @@ -44,7 +44,7 @@ vm-allocator = "0.1.0" vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } -zerocopy = { version = "0.8.23" } +zerocopy = { version = "0.8.24" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" From 2599a837e98beebb26aaaa1e85703e7df4f4ae85 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Mon, 24 Mar 2025 17:00:48 +0000 Subject: [PATCH 424/464] refactor: move initrd code into separate module Initrd code was spread across multiple modules, move common part of it into one and make freestanding `load_initrd_*` functions into methods for the `InitrdConfig` struct. Also change `initrd_load_addr` method to return an option instead of an error to remove extra error nesting. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/fdt.rs | 3 +- src/vmm/src/arch/aarch64/mod.rs | 16 ++-- src/vmm/src/arch/mod.rs | 9 -- src/vmm/src/arch/x86_64/mod.rs | 18 ++-- src/vmm/src/builder.rs | 145 ++------------------------------ src/vmm/src/initrd.rs | 140 ++++++++++++++++++++++++++++++ src/vmm/src/lib.rs | 3 + 7 files changed, 165 insertions(+), 169 deletions(-) create mode 100644 src/vmm/src/initrd.rs diff --git a/src/vmm/src/arch/aarch64/fdt.rs b/src/vmm/src/arch/aarch64/fdt.rs index c708add44bf..61200cb2148 100644 --- a/src/vmm/src/arch/aarch64/fdt.rs +++ b/src/vmm/src/arch/aarch64/fdt.rs @@ -12,11 +12,12 @@ use std::fmt::Debug; use vm_fdt::{Error as VmFdtError, FdtWriter, FdtWriterNode}; use vm_memory::GuestMemoryError; -use super::super::{DeviceType, InitrdConfig}; +use super::super::DeviceType; use super::cache_info::{CacheEntry, read_cache_config}; use super::gic::GICDevice; use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId}; +use crate::initrd::InitrdConfig; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap}; // This is a value for uniquely identifying the FDT node declaring the interrupt controller. diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index a09721e1775..cbd26a174a1 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -27,6 +27,7 @@ use self::gic::GICDevice; use crate::arch::DeviceType; use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::VmGenId; +use crate::initrd::InitrdConfig; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; /// Errors thrown while configuring aarch64 system. @@ -34,8 +35,6 @@ use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemo pub enum ConfigurationError { /// Failed to create a Flattened Device Tree for this aarch64 microVM: {0} SetupFDT(#[from] fdt::FdtError), - /// Failed to compute the initrd address. - InitrdAddress, /// Failed to write to guest memory. MemoryError(GuestMemoryError), } @@ -70,7 +69,7 @@ pub fn configure_system( device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, gic_device: &GICDevice, vmgenid: &Option, - initrd: &Option, + initrd: &Option, ) -> Result<(), ConfigurationError> { let fdt = fdt::create_fdt( guest_mem, @@ -94,21 +93,18 @@ pub fn get_kernel_start() -> u64 { } /// Returns the memory address where the initrd could be loaded. -pub fn initrd_load_addr( - guest_mem: &GuestMemoryMmap, - initrd_size: usize, -) -> Result { +pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Option { let round_to_pagesize = |size| (size + (super::GUEST_PAGE_SIZE - 1)) & !(super::GUEST_PAGE_SIZE - 1); match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) { Some(offset) => { if guest_mem.address_in_range(offset) { - Ok(offset.raw_value()) + Some(offset.raw_value()) } else { - Err(ConfigurationError::InitrdAddress) + None } } - None => Err(ConfigurationError::InitrdAddress), + None => None, } } diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index dd3ae178127..5ce6ab33f19 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -58,15 +58,6 @@ pub enum DeviceType { BootTimer, } -/// Type for passing information about the initrd in the guest memory. -#[derive(Debug)] -pub struct InitrdConfig { - /// Load address of initrd in guest memory - pub address: crate::vstate::memory::GuestAddress, - /// Size of initrd in guest memory - pub size: usize, -} - /// Default page size for the guest OS. pub const GUEST_PAGE_SIZE: usize = 4096; diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index ad680d89cff..040ed2708ad 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -39,8 +39,9 @@ use linux_loader::loader::elf::start_info::{ hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info, }; -use crate::arch::{BootProtocol, InitrdConfig, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; +use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::device_manager::resources::ResourceAllocator; +use crate::initrd::InitrdConfig; use crate::utils::{mib_to_bytes, u64_to_usize}; use crate::vstate::memory::{ Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, @@ -63,8 +64,6 @@ pub enum ConfigurationError { MpTableSetup(#[from] mptable::MptableError), /// Error writing the zero page of guest memory. ZeroPageSetup, - /// Failed to compute initrd address. - InitrdAddress, /// Error writing module entry to guest memory. ModlistSetup, /// Error writing memory map table to guest memory. @@ -107,21 +106,16 @@ pub fn get_kernel_start() -> u64 { } /// Returns the memory address where the initrd could be loaded. -pub fn initrd_load_addr( - guest_mem: &GuestMemoryMmap, - initrd_size: usize, -) -> Result { - let first_region = guest_mem - .find_region(GuestAddress::new(0)) - .ok_or(ConfigurationError::InitrdAddress)?; +pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Option { + let first_region = guest_mem.find_region(GuestAddress::new(0))?; let lowmem_size = u64_to_usize(first_region.len()); if lowmem_size < initrd_size { - return Err(ConfigurationError::InitrdAddress); + return None; } let align_to_pagesize = |address| address & !(super::GUEST_PAGE_SIZE - 1); - Ok(align_to_pagesize(lowmem_size - initrd_size) as u64) + Some(align_to_pagesize(lowmem_size - initrd_size) as u64) } /// Configures the system and should be called once per vm before starting vcpu threads. diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index cd1e063fb40..a15a5d9292b 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -6,7 +6,7 @@ #[cfg(target_arch = "x86_64")] use std::convert::TryFrom; use std::fmt::Debug; -use std::io::{self, Seek, SeekFrom}; +use std::io; #[cfg(feature = "gdb")] use std::sync::mpsc; use std::sync::{Arc, Mutex}; @@ -23,7 +23,6 @@ use linux_loader::loader::elf::PvhBootCapability; use linux_loader::loader::pe::PE as Loader; use userfaultfd::Uffd; use utils::time::TimestampUs; -use vm_memory::ReadVolatile; #[cfg(target_arch = "aarch64")] use vm_superio::Rtc; use vm_superio::Serial; @@ -31,8 +30,7 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] use crate::acpi; -use crate::arch::{BootProtocol, EntryPoint, InitrdConfig}; -use crate::builder::StartMicrovmError::Internal; +use crate::arch::{BootProtocol, EntryPoint}; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; use crate::cpu_config::templates::{ @@ -62,17 +60,17 @@ use crate::devices::virtio::rng::Entropy; use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend}; #[cfg(feature = "gdb")] use crate::gdb; +use crate::initrd::{InitrdConfig, InitrdError}; use crate::logger::{debug, error}; use crate::persist::{MicrovmState, MicrovmStateError}; use crate::resources::VmResources; use crate::seccomp::BpfThreadMap; use crate::snapshot::Persist; -use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootConfig; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; use crate::vstate::kvm::Kvm; -use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; +use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; use crate::vstate::vm::Vm; use crate::{EventManager, Vmm, VmmError, device_manager}; @@ -99,10 +97,8 @@ pub enum StartMicrovmError { CreateVMGenID(VmGenIdError), /// Invalid Memory Configuration: {0} GuestMemory(crate::vstate::memory::MemoryError), - /// Cannot load initrd due to an invalid memory configuration. - InitrdLoad, - /// Cannot load initrd due to an invalid image: {0} - InitrdRead(io::Error), + /// Error with initrd initialization: {0}. + Initrd(#[from] InitrdError), /// Internal error while starting microVM: {0} Internal(#[from] VmmError), /// Failed to get CPU template: {0} @@ -241,7 +237,7 @@ pub fn build_microvm_for_boot( .map_err(StartMicrovmError::GuestMemory)?; let entry_point = load_kernel(boot_config, &guest_memory)?; - let initrd = load_initrd_from_config(boot_config, &guest_memory)?; + let initrd = InitrdConfig::from_config(boot_config, &guest_memory)?; // Clone the command-line so that a failed boot doesn't pollute the original. #[allow(unused_mut)] let mut boot_cmdline = boot_config.cmdline.clone(); @@ -449,7 +445,7 @@ pub fn build_microvm_from_snapshot( vm_resources.machine_config.vcpu_count, microvm_state.kvm_state.kvm_cap_modifiers.clone(), ) - .map_err(Internal)?; + .map_err(StartMicrovmError::Internal)?; #[cfg(target_arch = "x86_64")] { @@ -603,68 +599,6 @@ fn load_kernel( }) } -fn load_initrd_from_config( - boot_cfg: &BootConfig, - vm_memory: &GuestMemoryMmap, -) -> Result, StartMicrovmError> { - use self::StartMicrovmError::InitrdRead; - - Ok(match &boot_cfg.initrd_file { - Some(f) => Some(load_initrd( - vm_memory, - &mut f.try_clone().map_err(InitrdRead)?, - )?), - None => None, - }) -} - -/// Loads the initrd from a file into the given memory slice. -/// -/// * `vm_memory` - The guest memory the initrd is written to. -/// * `image` - The initrd image. -/// -/// Returns the result of initrd loading -fn load_initrd( - vm_memory: &GuestMemoryMmap, - image: &mut F, -) -> Result -where - F: ReadVolatile + Seek + Debug, -{ - use self::StartMicrovmError::{InitrdLoad, InitrdRead}; - - // Get the image size - let size = match image.seek(SeekFrom::End(0)) { - Err(err) => return Err(InitrdRead(err)), - Ok(0) => { - return Err(InitrdRead(io::Error::new( - io::ErrorKind::InvalidData, - "Initrd image seek returned a size of zero", - ))); - } - Ok(s) => u64_to_usize(s), - }; - // Go back to the image start - image.seek(SeekFrom::Start(0)).map_err(InitrdRead)?; - - // Get the target address - let address = crate::arch::initrd_load_addr(vm_memory, size).map_err(|_| InitrdLoad)?; - - // Load the image into memory - let mut slice = vm_memory - .get_slice(GuestAddress(address), size) - .map_err(|_| InitrdLoad)?; - - image - .read_exact_volatile(&mut slice) - .map_err(|_| InitrdLoad)?; - - Ok(InitrdConfig { - address: GuestAddress(address), - size, - }) -} - /// Sets up the serial device. pub fn setup_serial_device( event_manager: &mut EventManager, @@ -1010,7 +944,6 @@ pub(crate) fn set_stdout_nonblocking() { #[cfg(test)] pub(crate) mod tests { - use std::io::Write; use linux_loader::cmdline::Cmdline; use vmm_sys_util::tempfile::TempFile; @@ -1024,7 +957,6 @@ pub(crate) mod tests { use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_RNG}; use crate::mmds::data_store::{Mmds, MmdsVersion}; use crate::mmds::ns::MmdsNetworkStack; - use crate::test_utils::{single_region_mem, single_region_mem_at}; use crate::utils::mib_to_bytes; use crate::vmm_config::balloon::{BALLOON_DEV_ID, BalloonBuilder, BalloonDeviceConfig}; use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE; @@ -1270,67 +1202,6 @@ pub(crate) mod tests { ); } - fn make_test_bin() -> Vec { - let mut fake_bin = Vec::new(); - fake_bin.resize(1_000_000, 0xAA); - fake_bin - } - - #[test] - // Test that loading the initrd is successful on different archs. - fn test_load_initrd() { - use crate::vstate::memory::GuestMemory; - let image = make_test_bin(); - - let mem_size: usize = image.len() * 2 + crate::arch::GUEST_PAGE_SIZE; - - let tempfile = TempFile::new().unwrap(); - let mut tempfile = tempfile.into_file(); - tempfile.write_all(&image).unwrap(); - - #[cfg(target_arch = "x86_64")] - let gm = single_region_mem(mem_size); - - #[cfg(target_arch = "aarch64")] - let gm = single_region_mem(mem_size + crate::arch::aarch64::layout::FDT_MAX_SIZE); - - let res = load_initrd(&gm, &mut tempfile); - let initrd = res.unwrap(); - assert!(gm.address_in_range(initrd.address)); - assert_eq!(initrd.size, image.len()); - } - - #[test] - fn test_load_initrd_no_memory() { - let gm = single_region_mem(79); - let image = make_test_bin(); - let tempfile = TempFile::new().unwrap(); - let mut tempfile = tempfile.into_file(); - tempfile.write_all(&image).unwrap(); - let res = load_initrd(&gm, &mut tempfile); - assert!( - matches!(res, Err(StartMicrovmError::InitrdLoad)), - "{:?}", - res - ); - } - - #[test] - fn test_load_initrd_unaligned() { - let image = vec![1, 2, 3, 4]; - let tempfile = TempFile::new().unwrap(); - let mut tempfile = tempfile.into_file(); - tempfile.write_all(&image).unwrap(); - let gm = single_region_mem_at(crate::arch::GUEST_PAGE_SIZE as u64 + 1, image.len() * 2); - - let res = load_initrd(&gm, &mut tempfile); - assert!( - matches!(res, Err(StartMicrovmError::InitrdLoad)), - "{:?}", - res - ); - } - #[test] fn test_attach_net_devices() { let mut event_manager = EventManager::new().expect("Unable to create EventManager"); diff --git a/src/vmm/src/initrd.rs b/src/vmm/src/initrd.rs new file mode 100644 index 00000000000..9dfcd8bc16e --- /dev/null +++ b/src/vmm/src/initrd.rs @@ -0,0 +1,140 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::fs::File; +use std::os::unix::fs::MetadataExt; + +use vm_memory::{GuestAddress, GuestMemory, ReadVolatile, VolatileMemoryError}; + +use crate::arch::initrd_load_addr; +use crate::utils::u64_to_usize; +use crate::vmm_config::boot_source::BootConfig; +use crate::vstate::memory::GuestMemoryMmap; + +/// Errors associated with initrd loading. +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum InitrdError { + /// Failed to compute the initrd address. + Address, + /// Cannot load initrd due to an invalid memory configuration. + Load, + /// Cannot image metadata: {0} + Metadata(std::io::Error), + /// Cannot copy initrd file fd: {0} + CloneFd(std::io::Error), + /// Cannot load initrd due to an invalid image: {0} + Read(VolatileMemoryError), +} + +/// Type for passing information about the initrd in the guest memory. +#[derive(Debug)] +pub struct InitrdConfig { + /// Load address of initrd in guest memory + pub address: GuestAddress, + /// Size of initrd in guest memory + pub size: usize, +} + +impl InitrdConfig { + /// Load initrd into guest memory based on the boot config. + pub fn from_config( + boot_cfg: &BootConfig, + vm_memory: &GuestMemoryMmap, + ) -> Result, InitrdError> { + Ok(match &boot_cfg.initrd_file { + Some(f) => { + let f = f.try_clone().map_err(InitrdError::CloneFd)?; + Some(Self::from_file(vm_memory, f)?) + } + None => None, + }) + } + + /// Loads the initrd from a file into guest memory. + pub fn from_file(vm_memory: &GuestMemoryMmap, mut file: File) -> Result { + let size = file.metadata().map_err(InitrdError::Metadata)?.size(); + let size = u64_to_usize(size); + let Some(address) = initrd_load_addr(vm_memory, size) else { + return Err(InitrdError::Address); + }; + let mut slice = vm_memory + .get_slice(GuestAddress(address), size) + .map_err(|_| InitrdError::Load)?; + file.read_exact_volatile(&mut slice) + .map_err(InitrdError::Read)?; + + Ok(InitrdConfig { + address: GuestAddress(address), + size, + }) + } +} + +#[cfg(test)] +mod tests { + use std::io::{Seek, SeekFrom, Write}; + + use vmm_sys_util::tempfile::TempFile; + + use super::*; + use crate::arch::GUEST_PAGE_SIZE; + use crate::test_utils::{single_region_mem, single_region_mem_at}; + + fn make_test_bin() -> Vec { + let mut fake_bin = Vec::new(); + fake_bin.resize(1_000_000, 0xAA); + fake_bin + } + + #[test] + // Test that loading the initrd is successful on different archs. + fn test_load_initrd() { + let image = make_test_bin(); + + let mem_size: usize = image.len() * 2 + GUEST_PAGE_SIZE; + + let tempfile = TempFile::new().unwrap(); + let mut tempfile = tempfile.into_file(); + tempfile.write_all(&image).unwrap(); + + #[cfg(target_arch = "x86_64")] + let gm = single_region_mem(mem_size); + + #[cfg(target_arch = "aarch64")] + let gm = single_region_mem(mem_size + crate::arch::aarch64::layout::FDT_MAX_SIZE); + + // Need to reset the cursor to read initrd properly. + tempfile.seek(SeekFrom::Start(0)).unwrap(); + let initrd = InitrdConfig::from_file(&gm, tempfile).unwrap(); + assert!(gm.address_in_range(initrd.address)); + assert_eq!(initrd.size, image.len()); + } + + #[test] + fn test_load_initrd_no_memory() { + let gm = single_region_mem(79); + let image = make_test_bin(); + let tempfile = TempFile::new().unwrap(); + let mut tempfile = tempfile.into_file(); + tempfile.write_all(&image).unwrap(); + + // Need to reset the cursor to read initrd properly. + tempfile.seek(SeekFrom::Start(0)).unwrap(); + let res = InitrdConfig::from_file(&gm, tempfile); + assert!(matches!(res, Err(InitrdError::Address)), "{:?}", res); + } + + #[test] + fn test_load_initrd_unaligned() { + let image = vec![1, 2, 3, 4]; + let tempfile = TempFile::new().unwrap(); + let mut tempfile = tempfile.into_file(); + tempfile.write_all(&image).unwrap(); + let gm = single_region_mem_at(GUEST_PAGE_SIZE as u64 + 1, image.len() * 2); + + // Need to reset the cursor to read initrd properly. + tempfile.seek(SeekFrom::Start(0)).unwrap(); + let res = InitrdConfig::from_file(&gm, tempfile); + assert!(matches!(res, Err(InitrdError::Address)), "{:?}", res); + } +} diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 993409dc819..2fb96045852 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -111,6 +111,9 @@ pub mod vmm_config; /// Module with virtual state structs. pub mod vstate; +/// Module with initrd. +pub mod initrd; + use std::collections::HashMap; use std::io; use std::os::unix::io::AsRawFd; From 97f602f7002aa5cb7e7c4a02674ccf8393bd940b Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 11:40:41 +0000 Subject: [PATCH 425/464] refactor: move load_kernel into arch module Move `load_kernel` arch specific functions into arch module per architecture. Make the function to accept the kernel `File` instead of the `BootConfig`. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 33 ++++++++++++- src/vmm/src/arch/mod.rs | 4 +- src/vmm/src/arch/x86_64/mod.rs | 44 +++++++++++++++++ src/vmm/src/builder.rs | 84 +++------------------------------ src/vmm/src/lib.rs | 2 - src/vmm/src/vstate/vcpu.rs | 8 ++-- 6 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index cbd26a174a1..fad3d81a1bb 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -20,11 +20,14 @@ use std::cmp::min; use std::collections::HashMap; use std::ffi::CString; use std::fmt::Debug; +use std::fs::File; +use linux_loader::loader::KernelLoader; +use linux_loader::loader::pe::PE as Loader; use vm_memory::GuestMemoryError; use self::gic::GICDevice; -use crate::arch::DeviceType; +use crate::arch::{BootProtocol, DeviceType, EntryPoint}; use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::VmGenId; use crate::initrd::InitrdConfig; @@ -37,6 +40,10 @@ pub enum ConfigurationError { SetupFDT(#[from] fdt::FdtError), /// Failed to write to guest memory. MemoryError(GuestMemoryError), + /// Cannot copy kernel file fd + KernelFile, + /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} + KernelLoader(#[from] linux_loader::loader::Error), } /// The start of the memory area reserved for MMIO devices. @@ -123,6 +130,30 @@ fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 { layout::DRAM_MEM_START } +/// Load linux kernel into guest memory. +pub fn load_kernel( + kernel: &File, + guest_memory: &GuestMemoryMmap, +) -> Result { + // Need to clone the File because reading from it + // mutates it. + let mut kernel_file = kernel + .try_clone() + .map_err(|_| ConfigurationError::KernelFile)?; + + let entry_addr = Loader::load( + guest_memory, + Some(GuestAddress(get_kernel_start())), + &mut kernel_file, + None, + )?; + + Ok(EntryPoint { + entry_addr: entry_addr.kernel_load, + protocol: BootProtocol::LinuxBoot, + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 5ce6ab33f19..6c0b3e123dd 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -22,7 +22,7 @@ pub use aarch64::vm::{ArchVm, ArchVmError, VmState}; pub use aarch64::{ ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr, layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, - layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, + layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, load_kernel, }; /// Module for x86_64 related functionality. @@ -40,7 +40,7 @@ pub use x86_64::{ ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::CMDLINE_MAX_SIZE, layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, - layout::SYSTEM_MEM_START, + layout::SYSTEM_MEM_START, load_kernel, }; /// Types of devices that can get attached to this platform. diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 040ed2708ad..7f79c58b18f 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -31,14 +31,20 @@ pub mod xstate; #[allow(missing_docs)] pub mod generated; +use std::fs::File; + use linux_loader::configurator::linux::LinuxBootConfigurator; use linux_loader::configurator::pvh::PvhBootConfigurator; use linux_loader::configurator::{BootConfigurator, BootParams}; use linux_loader::loader::bootparam::boot_params; +use linux_loader::loader::elf::Elf as Loader; use linux_loader::loader::elf::start_info::{ hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info, }; +use linux_loader::loader::{KernelLoader, PvhBootCapability}; +use log::debug; +use super::EntryPoint; use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::device_manager::resources::ResourceAllocator; use crate::initrd::InitrdConfig; @@ -70,6 +76,10 @@ pub enum ConfigurationError { MemmapTableSetup, /// Error writing hvm_start_info to guest memory. StartInfoSetup, + /// Cannot copy kernel file fd + KernelFile, + /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} + KernelLoader(#[from] linux_loader::loader::Error), } /// First address that cannot be addressed using 32 bit anymore. @@ -354,6 +364,40 @@ fn add_e820_entry( Ok(()) } +/// Load linux kernel into guest memory. +pub fn load_kernel( + kernel: &File, + guest_memory: &GuestMemoryMmap, +) -> Result { + // Need to clone the File because reading from it + // mutates it. + let mut kernel_file = kernel + .try_clone() + .map_err(|_| ConfigurationError::KernelFile)?; + + let entry_addr = Loader::load( + guest_memory, + None, + &mut kernel_file, + Some(GuestAddress(get_kernel_start())), + )?; + + let mut entry_point_addr: GuestAddress = entry_addr.kernel_load; + let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot; + if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap { + // Use the PVH kernel entry point to boot the guest + entry_point_addr = pvh_entry_addr; + boot_prot = BootProtocol::PvhBoot; + } + + debug!("Kernel loaded using {boot_prot}"); + + Ok(EntryPoint { + entry_addr: entry_point_addr, + protocol: boot_prot, + }) +} + #[cfg(test)] mod tests { use linux_loader::loader::bootparam::boot_e820_entry; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index a15a5d9292b..335f1736527 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -14,13 +14,6 @@ use std::sync::{Arc, Mutex}; use event_manager::{MutEventSubscriber, SubscriberOps}; use libc::EFD_NONBLOCK; use linux_loader::cmdline::Cmdline as LoaderKernelCmdline; -use linux_loader::loader::KernelLoader; -#[cfg(target_arch = "x86_64")] -use linux_loader::loader::elf::Elf as Loader; -#[cfg(target_arch = "x86_64")] -use linux_loader::loader::elf::PvhBootCapability; -#[cfg(target_arch = "aarch64")] -use linux_loader::loader::pe::PE as Loader; use userfaultfd::Uffd; use utils::time::TimestampUs; #[cfg(target_arch = "aarch64")] @@ -30,7 +23,7 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] use crate::acpi; -use crate::arch::{BootProtocol, EntryPoint}; +use crate::arch::{ConfigurationError, EntryPoint, load_kernel}; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; use crate::cpu_config::templates::{ @@ -66,11 +59,10 @@ use crate::persist::{MicrovmState, MicrovmStateError}; use crate::resources::VmResources; use crate::seccomp::BpfThreadMap; use crate::snapshot::Persist; -use crate::vmm_config::boot_source::BootConfig; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; use crate::vstate::kvm::Kvm; -use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; +use crate::vstate::memory::GuestMemoryMmap; use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; use crate::vstate::vm::Vm; use crate::{EventManager, Vmm, VmmError, device_manager}; @@ -83,7 +75,7 @@ pub enum StartMicrovmError { /// Unable to attach the VMGenID device: {0} AttachVmgenidDevice(kvm_ioctls::Error), /// System configuration error: {0} - ConfigureSystem(crate::arch::ConfigurationError), + ConfigureSystem(#[from] ConfigurationError), /// Failed to create guest config: {0} CreateGuestConfig(#[from] GuestConfigError), /// Cannot create network device: {0} @@ -105,8 +97,6 @@ pub enum StartMicrovmError { GetCpuTemplate(#[from] GetCpuTemplateError), /// Invalid kernel command line: {0} KernelCmdline(String), - /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} - KernelLoader(linux_loader::loader::Error), /// Cannot load command line string: {0} LoadCommandline(linux_loader::loader::Error), /// Cannot start microvm without kernel configuration. @@ -236,7 +226,7 @@ pub fn build_microvm_for_boot( .allocate_guest_memory() .map_err(StartMicrovmError::GuestMemory)?; - let entry_point = load_kernel(boot_config, &guest_memory)?; + let entry_point = load_kernel(&boot_config.kernel_file, &guest_memory)?; let initrd = InitrdConfig::from_config(boot_config, &guest_memory)?; // Clone the command-line so that a failed boot doesn't pollute the original. #[allow(unused_mut)] @@ -541,64 +531,6 @@ pub fn build_microvm_from_snapshot( Ok(vmm) } -#[cfg(target_arch = "x86_64")] -fn load_kernel( - boot_config: &BootConfig, - guest_memory: &GuestMemoryMmap, -) -> Result { - let mut kernel_file = boot_config - .kernel_file - .try_clone() - .map_err(VmmError::KernelFile)?; - - let entry_addr = Loader::load::( - guest_memory, - None, - &mut kernel_file, - Some(GuestAddress(crate::arch::get_kernel_start())), - ) - .map_err(StartMicrovmError::KernelLoader)?; - - let mut entry_point_addr: GuestAddress = entry_addr.kernel_load; - let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot; - if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap { - // Use the PVH kernel entry point to boot the guest - entry_point_addr = pvh_entry_addr; - boot_prot = BootProtocol::PvhBoot; - } - - debug!("Kernel loaded using {boot_prot}"); - - Ok(EntryPoint { - entry_addr: entry_point_addr, - protocol: boot_prot, - }) -} - -#[cfg(target_arch = "aarch64")] -fn load_kernel( - boot_config: &BootConfig, - guest_memory: &GuestMemoryMmap, -) -> Result { - let mut kernel_file = boot_config - .kernel_file - .try_clone() - .map_err(VmmError::KernelFile)?; - - let entry_addr = Loader::load::( - guest_memory, - Some(GuestAddress(crate::arch::get_kernel_start())), - &mut kernel_file, - None, - ) - .map_err(StartMicrovmError::KernelLoader)?; - - Ok(EntryPoint { - entry_addr: entry_addr.kernel_load, - protocol: BootProtocol::LinuxBoot, - }) -} - /// Sets up the serial device. pub fn setup_serial_device( event_manager: &mut EventManager, @@ -725,7 +657,7 @@ pub fn configure_system_for_boot( linux_loader::loader::load_cmdline::( vmm.guest_memory(), - GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), + crate::vstate::memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), &boot_cmdline, ) .map_err(LoadCommandline)?; @@ -737,8 +669,7 @@ pub fn configure_system_for_boot( initrd, vcpu_config.vcpu_count, entry_point.protocol, - ) - .map_err(ConfigureSystem)?; + )?; // Create ACPI tables and write them in guest memory // For the time being we only support ACPI in x86_64 @@ -777,8 +708,7 @@ pub fn configure_system_for_boot( vmm.vm.get_irqchip(), &vmm.acpi_device_manager.vmgenid, initrd, - ) - .map_err(ConfigureSystem)?; + )?; } Ok(()) } diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 2fb96045852..f6c283c1da2 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -221,8 +221,6 @@ pub enum VmmError { EventFd(io::Error), /// I8042 error: {0} I8042Error(devices::legacy::I8042DeviceError), - /// Cannot access kernel file: {0} - KernelFile(io::Error), #[cfg(target_arch = "x86_64")] /// Cannot add devices to the legacy I/O Bus. {0} LegacyIOBus(device_manager::legacy::LegacyDeviceError), diff --git a/src/vmm/src/vstate/vcpu.rs b/src/vmm/src/vstate/vcpu.rs index b7de0017e46..4e1bf8970a0 100644 --- a/src/vmm/src/vstate/vcpu.rs +++ b/src/vmm/src/vstate/vcpu.rs @@ -771,7 +771,6 @@ pub(crate) mod tests { use super::*; use crate::RECV_TIMEOUT_SEC; use crate::arch::{BootProtocol, EntryPoint}; - use crate::builder::StartMicrovmError; use crate::devices::BusDevice; use crate::devices::bus::DummyDevice; use crate::seccomp::get_empty_filters; @@ -952,12 +951,11 @@ pub(crate) mod tests { &mut kernel_file, Some(GuestAddress(crate::arch::get_kernel_start())), ) - .map_err(StartMicrovmError::KernelLoader); + .unwrap(); #[cfg(target_arch = "aarch64")] let entry_addr = - linux_loader::loader::pe::PE::load(vm_memory, None, &mut kernel_file, None) - .map_err(StartMicrovmError::KernelLoader); - entry_addr.unwrap().kernel_load + linux_loader::loader::pe::PE::load(vm_memory, None, &mut kernel_file, None).unwrap(); + entry_addr.kernel_load } fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd, GuestMemoryMmap) { From 8379fcd39e95e2c4adef20eb3d97922e11ef302c Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 12:19:01 +0000 Subject: [PATCH 426/464] refactor: move configure_system_for_boot into arch module Split `configure_system_for_boot` into 2 arch specific functions and move it into arch module. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 94 ++++++++++++++++++--- src/vmm/src/arch/mod.rs | 18 ++-- src/vmm/src/arch/x86_64/mod.rs | 109 ++++++++++++++++++++---- src/vmm/src/builder.rs | 143 ++------------------------------ src/vmm/src/lib.rs | 7 +- 5 files changed, 192 insertions(+), 179 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index fad3d81a1bb..11369ae0a16 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -22,16 +22,23 @@ use std::ffi::CString; use std::fmt::Debug; use std::fs::File; -use linux_loader::loader::KernelLoader; use linux_loader::loader::pe::PE as Loader; +use linux_loader::loader::{Cmdline, KernelLoader}; use vm_memory::GuestMemoryError; use self::gic::GICDevice; +use crate::arch::aarch64::regs::Aarch64RegisterVec; +use crate::arch::aarch64::vcpu::{VcpuArchError, get_registers}; use crate::arch::{BootProtocol, DeviceType, EntryPoint}; +use crate::cpu_config::aarch64::{CpuConfiguration, CpuConfigurationError}; +use crate::cpu_config::templates::CustomCpuTemplate; use crate::device_manager::mmio::MMIODeviceInfo; use crate::devices::acpi::vmgenid::VmGenId; use crate::initrd::InitrdConfig; +use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; +use crate::vstate::vcpu::KvmVcpuError; +use crate::{Vcpu, VcpuConfig, Vmm}; /// Errors thrown while configuring aarch64 system. #[derive(Debug, thiserror::Error, displaydoc::Display)] @@ -44,6 +51,14 @@ pub enum ConfigurationError { KernelFile, /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} KernelLoader(#[from] linux_loader::loader::Error), + /// Error initializing the vcpu: {0} + VcpuInit(KvmVcpuError), + /// Error configuring the vcpu: {0} + VcpuConfigure(KvmVcpuError), + /// Error reading vcpu registers: {0} + VcpuGetRegs(VcpuArchError), + /// Error applying vcpu template: {0} + VcpuApplyTemplate(CpuConfigurationError), } /// The start of the memory area reserved for MMIO devices. @@ -58,18 +73,73 @@ pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> { vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)] } +/// Configures the system for booting Linux. +pub fn configure_system_for_boot( + vmm: &mut Vmm, + vcpus: &mut [Vcpu], + machine_config: &MachineConfig, + cpu_template: &CustomCpuTemplate, + entry_point: EntryPoint, + initrd: &Option, + boot_cmdline: Cmdline, +) -> Result<(), ConfigurationError> { + // Construct the base CpuConfiguration to apply CPU template onto. + let cpu_config = { + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu + .init(&cpu_template.vcpu_features) + .map_err(ConfigurationError::VcpuInit)?; + } + + let mut regs = Aarch64RegisterVec::default(); + get_registers(&vcpus[0].kvm_vcpu.fd, &cpu_template.reg_list(), &mut regs) + .map_err(ConfigurationError::VcpuGetRegs)?; + CpuConfiguration { regs } + }; + + // Apply CPU template to the base CpuConfiguration. + let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template) + .map_err(ConfigurationError::VcpuApplyTemplate)?; + + let vcpu_config = VcpuConfig { + vcpu_count: machine_config.vcpu_count, + smt: machine_config.smt, + cpu_config, + }; + + let optional_capabilities = vmm.kvm.optional_capabilities(); + // Configure vCPUs with normalizing and setting the generated CPU configuration. + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu + .configure( + vmm.guest_memory(), + entry_point, + &vcpu_config, + &optional_capabilities, + ) + .map_err(ConfigurationError::VcpuConfigure)?; + } + let vcpu_mpidr = vcpus + .iter_mut() + .map(|cpu| cpu.kvm_vcpu.get_mpidr()) + .collect(); + let cmdline = boot_cmdline + .as_cstring() + .expect("Cannot create cstring from cmdline string"); + configure_system( + &vmm.guest_memory, + cmdline, + vcpu_mpidr, + vmm.mmio_device_manager.get_device_info(), + vmm.vm.get_irqchip(), + &vmm.acpi_device_manager.vmgenid, + initrd, + )?; + Ok(()) +} + /// Configures the system and should be called once per vm before starting vcpu threads. -/// For aarch64, we only setup the FDT. -/// -/// # Arguments -/// -/// * `guest_mem` - The memory to be used by the guest. -/// * `cmdline_cstring` - The kernel commandline. -/// * `vcpu_mpidr` - Array of MPIDR register values per vcpu. -/// * `device_info` - A hashmap containing the attached devices for building FDT device nodes. -/// * `gic_device` - The GIC device. -/// * `initrd` - Information about an optional initrd. -pub fn configure_system( +fn configure_system( guest_mem: &GuestMemoryMmap, cmdline_cstring: CString, vcpu_mpidr: Vec, diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 6c0b3e123dd..61d65fea1a5 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -20,9 +20,10 @@ pub use aarch64::vcpu::*; pub use aarch64::vm::{ArchVm, ArchVmError, VmState}; #[cfg(target_arch = "aarch64")] pub use aarch64::{ - ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, - get_kernel_start, initrd_load_addr, layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, - layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, load_kernel, + ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, + configure_system_for_boot, get_kernel_start, initrd_load_addr, layout::CMDLINE_MAX_SIZE, + layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, + load_kernel, }; /// Module for x86_64 related functionality. @@ -35,12 +36,13 @@ pub use x86_64::kvm::{Kvm, KvmArchError}; pub use x86_64::vcpu::*; #[cfg(target_arch = "x86_64")] pub use x86_64::vm::{ArchVm, ArchVmError, VmState}; + #[cfg(target_arch = "x86_64")] -pub use x86_64::{ - ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system, - get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::CMDLINE_MAX_SIZE, - layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, - layout::SYSTEM_MEM_START, load_kernel, +pub use crate::arch::x86_64::{ + ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, + configure_system_for_boot, get_kernel_start, initrd_load_addr, layout::APIC_ADDR, + layout::CMDLINE_MAX_SIZE, layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, + layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, load_kernel, }; /// Types of devices that can get attached to this platform. diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 7f79c58b18f..cc75b941736 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -41,17 +41,23 @@ use linux_loader::loader::elf::Elf as Loader; use linux_loader::loader::elf::start_info::{ hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info, }; -use linux_loader::loader::{KernelLoader, PvhBootCapability}; +use linux_loader::loader::{Cmdline, KernelLoader, PvhBootCapability, load_cmdline}; use log::debug; use super::EntryPoint; +use crate::acpi::create_acpi_tables; use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; +use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; +use crate::cpu_config::x86_64::{CpuConfiguration, cpuid}; use crate::device_manager::resources::ResourceAllocator; use crate::initrd::InitrdConfig; use crate::utils::{mib_to_bytes, u64_to_usize}; +use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{ Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, }; +use crate::vstate::vcpu::KvmVcpuConfigureError; +use crate::{Vcpu, VcpuConfig, Vmm}; // Value taken from https://elixir.bootlin.com/linux/v5.10.68/source/arch/x86/include/uapi/asm/e820.h#L31 // Usable normal RAM @@ -62,7 +68,7 @@ const E820_RESERVED: u32 = 2; const MEMMAP_TYPE_RAM: u32 = 1; /// Errors thrown while configuring x86_64 system. -#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +#[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum ConfigurationError { /// Invalid e820 setup params. E820Configuration, @@ -79,7 +85,15 @@ pub enum ConfigurationError { /// Cannot copy kernel file fd KernelFile, /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} - KernelLoader(#[from] linux_loader::loader::Error), + KernelLoader(linux_loader::loader::Error), + /// Cannot load command line string: {0} + LoadCommandline(linux_loader::loader::Error), + /// Failed to create guest config: {0} + CreateGuestConfig(#[from] GuestConfigError), + /// Error configuring the vcpu for boot: {0} + VcpuConfigure(#[from] KvmVcpuConfigureError), + /// Error configuring ACPI: {0} + Acpi(#[from] crate::acpi::AcpiError), } /// First address that cannot be addressed using 32 bit anymore. @@ -128,17 +142,79 @@ pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Opti Some(align_to_pagesize(lowmem_size - initrd_size) as u64) } +/// Configures the system for booting Linux. +pub fn configure_system_for_boot( + vmm: &mut Vmm, + vcpus: &mut [Vcpu], + machine_config: &MachineConfig, + cpu_template: &CustomCpuTemplate, + entry_point: EntryPoint, + initrd: &Option, + boot_cmdline: Cmdline, +) -> Result<(), ConfigurationError> { + // Construct the base CpuConfiguration to apply CPU template onto. + let cpu_config = { + let cpuid = cpuid::Cpuid::try_from(vmm.kvm.supported_cpuid.clone()) + .map_err(GuestConfigError::CpuidFromKvmCpuid)?; + let msrs = vcpus[0] + .kvm_vcpu + .get_msrs(cpu_template.msr_index_iter()) + .map_err(GuestConfigError::VcpuIoctl)?; + CpuConfiguration { cpuid, msrs } + }; + + // Apply CPU template to the base CpuConfiguration. + let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template)?; + + let vcpu_config = VcpuConfig { + vcpu_count: machine_config.vcpu_count, + smt: machine_config.smt, + cpu_config, + }; + + // Configure vCPUs with normalizing and setting the generated CPU configuration. + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu + .configure(vmm.guest_memory(), entry_point, &vcpu_config)?; + } + + // Write the kernel command line to guest memory. This is x86_64 specific, since on + // aarch64 the command line will be specified through the FDT. + let cmdline_size = boot_cmdline + .as_cstring() + .map(|cmdline_cstring| cmdline_cstring.as_bytes_with_nul().len()) + .expect("Cannot create cstring from cmdline string"); + + load_cmdline( + vmm.guest_memory(), + GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), + &boot_cmdline, + ) + .map_err(ConfigurationError::LoadCommandline)?; + configure_system( + &vmm.guest_memory, + &mut vmm.resource_allocator, + GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), + cmdline_size, + initrd, + vcpu_config.vcpu_count, + entry_point.protocol, + )?; + + // Create ACPI tables and write them in guest memory + // For the time being we only support ACPI in x86_64 + create_acpi_tables( + &vmm.guest_memory, + &mut vmm.resource_allocator, + &vmm.mmio_device_manager, + &vmm.acpi_device_manager, + vcpus, + )?; + Ok(()) +} + /// Configures the system and should be called once per vm before starting vcpu threads. -/// -/// # Arguments -/// -/// * `guest_mem` - The memory to be used by the guest. -/// * `cmdline_addr` - Address in `guest_mem` where the kernel command line was loaded. -/// * `cmdline_size` - Size of the kernel command line in bytes including the null terminator. -/// * `initrd` - Information about where the ramdisk image was loaded in the `guest_mem`. -/// * `num_cpus` - Number of virtual CPUs the guest will have. -/// * `boot_prot` - Boot protocol that will be used to boot the guest. -pub fn configure_system( +fn configure_system( guest_mem: &GuestMemoryMmap, resource_allocator: &mut ResourceAllocator, cmdline_addr: GuestAddress, @@ -380,7 +456,8 @@ pub fn load_kernel( None, &mut kernel_file, Some(GuestAddress(get_kernel_start())), - )?; + ) + .map_err(ConfigurationError::KernelLoader)?; let mut entry_point_addr: GuestAddress = entry_addr.kernel_load; let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot; @@ -435,10 +512,10 @@ mod tests { 1, BootProtocol::LinuxBoot, ); - assert_eq!( + assert!(matches!( config_err.unwrap_err(), super::ConfigurationError::MpTableSetup(mptable::MptableError::NotEnoughMemory) - ); + )); // Now assigning some memory that falls before the 32bit memory hole. let mem_size = mib_to_bytes(128); diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 335f1736527..631be63d9ad 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -3,8 +3,6 @@ //! Enables pre-boot setup, instantiation and booting of a Firecracker VMM. -#[cfg(target_arch = "x86_64")] -use std::convert::TryFrom; use std::fmt::Debug; use std::io; #[cfg(feature = "gdb")] @@ -21,14 +19,11 @@ use vm_superio::Rtc; use vm_superio::Serial; use vmm_sys_util::eventfd::EventFd; -#[cfg(target_arch = "x86_64")] -use crate::acpi; -use crate::arch::{ConfigurationError, EntryPoint, load_kernel}; +use crate::arch::{ConfigurationError, configure_system_for_boot, load_kernel}; #[cfg(target_arch = "aarch64")] use crate::construct_kvm_mpidrs; use crate::cpu_config::templates::{ - CpuConfiguration, CustomCpuTemplate, GetCpuTemplate, GetCpuTemplateError, GuestConfigError, - KvmCapability, + GetCpuTemplate, GetCpuTemplateError, GuestConfigError, KvmCapability, }; use crate::device_manager::acpi::ACPIDeviceManager; #[cfg(target_arch = "x86_64")] @@ -60,10 +55,10 @@ use crate::resources::VmResources; use crate::seccomp::BpfThreadMap; use crate::snapshot::Persist; use crate::vmm_config::instance_info::InstanceInfo; -use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError}; +use crate::vmm_config::machine_config::MachineConfigError; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestMemoryMmap; -use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError}; +use crate::vstate::vcpu::{Vcpu, VcpuError}; use crate::vstate::vm::Vm; use crate::{EventManager, Vmm, VmmError, device_manager}; @@ -117,9 +112,8 @@ pub enum StartMicrovmError { SetVmResources(MachineConfigError), /// Cannot create the entropy device: {0} CreateEntropyDevice(crate::devices::virtio::rng::EntropyError), - /// Error configuring ACPI: {0} - #[cfg(target_arch = "x86_64")] - Acpi(#[from] crate::acpi::AcpiError), + /// Failed to allocate guest resource: {0} + AllocateResources(#[from] vm_allocator::Error), /// Error starting GDB debug session #[cfg(feature = "gdb")] GdbServer(gdb::target::GdbTargetError), @@ -588,131 +582,6 @@ fn attach_legacy_devices_aarch64( .map_err(VmmError::RegisterMMIODevice) } -/// Configures the system for booting Linux. -#[cfg_attr(target_arch = "aarch64", allow(unused))] -pub fn configure_system_for_boot( - vmm: &mut Vmm, - vcpus: &mut [Vcpu], - machine_config: &MachineConfig, - cpu_template: &CustomCpuTemplate, - entry_point: EntryPoint, - initrd: &Option, - boot_cmdline: LoaderKernelCmdline, -) -> Result<(), StartMicrovmError> { - use self::StartMicrovmError::*; - - // Construct the base CpuConfiguration to apply CPU template onto. - #[cfg(target_arch = "x86_64")] - let cpu_config = { - use crate::cpu_config::x86_64::cpuid; - let cpuid = cpuid::Cpuid::try_from(vmm.kvm.supported_cpuid.clone()) - .map_err(GuestConfigError::CpuidFromKvmCpuid)?; - let msrs = vcpus[0] - .kvm_vcpu - .get_msrs(cpu_template.msr_index_iter()) - .map_err(GuestConfigError::VcpuIoctl)?; - CpuConfiguration { cpuid, msrs } - }; - - #[cfg(target_arch = "aarch64")] - let cpu_config = { - use crate::arch::aarch64::regs::Aarch64RegisterVec; - use crate::arch::aarch64::vcpu::get_registers; - - for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .init(&cpu_template.vcpu_features) - .map_err(VmmError::VcpuInit)?; - } - - let mut regs = Aarch64RegisterVec::default(); - get_registers(&vcpus[0].kvm_vcpu.fd, &cpu_template.reg_list(), &mut regs) - .map_err(GuestConfigError)?; - CpuConfiguration { regs } - }; - - // Apply CPU template to the base CpuConfiguration. - let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template)?; - - let vcpu_config = VcpuConfig { - vcpu_count: machine_config.vcpu_count, - smt: machine_config.smt, - cpu_config, - }; - - #[cfg(target_arch = "x86_64")] - { - // Configure vCPUs with normalizing and setting the generated CPU configuration. - for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .configure(vmm.guest_memory(), entry_point, &vcpu_config) - .map_err(VmmError::VcpuConfigure)?; - } - - // Write the kernel command line to guest memory. This is x86_64 specific, since on - // aarch64 the command line will be specified through the FDT. - let cmdline_size = boot_cmdline - .as_cstring() - .map(|cmdline_cstring| cmdline_cstring.as_bytes_with_nul().len())?; - - linux_loader::loader::load_cmdline::( - vmm.guest_memory(), - crate::vstate::memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), - &boot_cmdline, - ) - .map_err(LoadCommandline)?; - crate::arch::x86_64::configure_system( - &vmm.guest_memory, - &mut vmm.resource_allocator, - crate::vstate::memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), - cmdline_size, - initrd, - vcpu_config.vcpu_count, - entry_point.protocol, - )?; - - // Create ACPI tables and write them in guest memory - // For the time being we only support ACPI in x86_64 - acpi::create_acpi_tables( - &vmm.guest_memory, - &mut vmm.resource_allocator, - &vmm.mmio_device_manager, - &vmm.acpi_device_manager, - vcpus, - )?; - } - #[cfg(target_arch = "aarch64")] - { - let optional_capabilities = vmm.kvm.optional_capabilities(); - // Configure vCPUs with normalizing and setting the generated CPU configuration. - for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .configure( - vmm.guest_memory(), - entry_point, - &vcpu_config, - &optional_capabilities, - ) - .map_err(VmmError::VcpuConfigure)?; - } - let vcpu_mpidr = vcpus - .iter_mut() - .map(|cpu| cpu.kvm_vcpu.get_mpidr()) - .collect(); - let cmdline = boot_cmdline.as_cstring()?; - crate::arch::aarch64::configure_system( - &vmm.guest_memory, - cmdline, - vcpu_mpidr, - vmm.mmio_device_manager.get_device_info(), - vmm.vm.get_irqchip(), - &vmm.acpi_device_manager.vmgenid, - initrd, - )?; - } - Ok(()) -} - /// Attaches a VirtioDevice device to the device manager and event manager. fn attach_virtio_device( event_manager: &mut EventManager, diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index f6c283c1da2..9224c2edb6b 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -131,7 +131,7 @@ use vmm_sys_util::epoll::EventSet; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::terminal::Terminal; use vstate::kvm::Kvm; -use vstate::vcpu::{self, KvmVcpuConfigureError, StartThreadedError, VcpuSendEventError}; +use vstate::vcpu::{self, StartThreadedError, VcpuSendEventError}; use crate::arch::DeviceType; use crate::cpu_config::templates::CpuConfiguration; @@ -234,17 +234,12 @@ pub enum VmmError { Serial(io::Error), /// Error creating timer fd: {0} TimerFd(io::Error), - /// Error configuring the vcpu for boot: {0} - VcpuConfigure(KvmVcpuConfigureError), /// Error creating the vcpu: {0} VcpuCreate(vstate::vcpu::VcpuError), /// Cannot send event to vCPU. {0} VcpuEvent(vstate::vcpu::VcpuError), /// Cannot create a vCPU handle. {0} VcpuHandle(vstate::vcpu::VcpuError), - #[cfg(target_arch = "aarch64")] - /// Error initializing the vcpu: {0} - VcpuInit(vstate::vcpu::KvmVcpuError), /// Failed to start vCPUs VcpuStart(StartVcpusError), /// Failed to pause the vCPUs. From 6fdb2b010168c21e8a37b7979ff4ff44fed7f582 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 13:34:24 +0000 Subject: [PATCH 427/464] refactor: remove getter for guest memory from Vmm Some places were accessing `guest_memory` directly while others were using getter. Remove getter to make accesses consistent. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 2 +- src/vmm/src/arch/x86_64/mod.rs | 4 ++-- src/vmm/src/builder.rs | 2 +- src/vmm/src/device_manager/persist.rs | 2 +- src/vmm/src/gdb/arch/aarch64.rs | 2 +- src/vmm/src/gdb/target.rs | 4 ++-- src/vmm/src/lib.rs | 9 ++------- src/vmm/src/persist.rs | 12 ++++++------ 8 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 11369ae0a16..d74712b8ca1 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -112,7 +112,7 @@ pub fn configure_system_for_boot( for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu .configure( - vmm.guest_memory(), + &vmm.guest_memory, entry_point, &vcpu_config, &optional_capabilities, diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index cc75b941736..4f0707068b1 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -175,7 +175,7 @@ pub fn configure_system_for_boot( // Configure vCPUs with normalizing and setting the generated CPU configuration. for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu - .configure(vmm.guest_memory(), entry_point, &vcpu_config)?; + .configure(&vmm.guest_memory, entry_point, &vcpu_config)?; } // Write the kernel command line to guest memory. This is x86_64 specific, since on @@ -186,7 +186,7 @@ pub fn configure_system_for_boot( .expect("Cannot create cstring from cmdline string"); load_cmdline( - vmm.guest_memory(), + &vmm.guest_memory, GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), &boot_cmdline, ) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 631be63d9ad..360b255be44 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -596,7 +596,7 @@ fn attach_virtio_device( event_manager.add_subscriber(device.clone()); // The device mutex mustn't be locked here otherwise it will deadlock. - let device = MmioTransport::new(vmm.guest_memory().clone(), device, is_vhost_user); + let device = MmioTransport::new(vmm.guest_memory.clone(), device, is_vhost_user); vmm.mmio_device_manager .register_mmio_virtio_for_boot( vmm.vm.fd(), diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index ffab7b81bfd..0b8ad8eb04d 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -805,7 +805,7 @@ mod tests { let device_states: DeviceStates = Snapshot::deserialize(&mut buf.as_slice()).unwrap(); let vm_resources = &mut VmResources::default(); let restore_args = MMIODevManagerConstructorArgs { - mem: vmm.guest_memory(), + mem: &vmm.guest_memory, vm: vmm.vm.fd(), event_manager: &mut event_manager, resource_allocator: &mut resource_allocator, diff --git a/src/vmm/src/gdb/arch/aarch64.rs b/src/vmm/src/gdb/arch/aarch64.rs index efd5ad8ae01..9504a48fcc5 100644 --- a/src/vmm/src/gdb/arch/aarch64.rs +++ b/src/vmm/src/gdb/arch/aarch64.rs @@ -63,7 +63,7 @@ const PTE_ADDRESS_MASK: u64 = !0b111u64; /// Read a u64 value from a guest memory address fn read_address(vmm: &Vmm, address: u64) -> Result { let mut buf = [0; 8]; - vmm.guest_memory().read(&mut buf, GuestAddress(address))?; + vmm.guest_memory.read(&mut buf, GuestAddress(address))?; Ok(u64::from_le_bytes(buf)) } diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index c3293db1607..3ff96d0c8b5 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -399,7 +399,7 @@ impl MultiThreadBase for FirecrackerTarget { GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); - vmm.guest_memory() + vmm.guest_memory .read(&mut data[..read_len], GuestAddress(gpa as u64)) .map_err(|e| { error!("Error reading memory {e:?} gpa is {gpa}"); @@ -433,7 +433,7 @@ impl MultiThreadBase for FirecrackerTarget { GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); - vmm.guest_memory() + vmm.guest_memory .write(&data[..write_len], GuestAddress(gpa)) .map_err(|e| { error!("Error {e:?} writing memory at {gpa:#X}"); diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 9224c2edb6b..5f173d3ae9c 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -444,11 +444,6 @@ impl Vmm { Ok(()) } - /// Returns a reference to the inner `GuestMemoryMmap` object. - pub fn guest_memory(&self) -> &GuestMemoryMmap { - &self.guest_memory - } - /// Sets RDA bit in serial console pub fn emulate_serial_init(&self) -> Result<(), EmulateSerialInitError> { // When restoring from a previously saved state, there is no serial @@ -526,7 +521,7 @@ impl Vmm { }; let device_states = self.mmio_device_manager.save(); - let memory_state = self.guest_memory().describe(); + let memory_state = self.guest_memory.describe(); let acpi_dev_state = self.acpi_device_manager.save(); Ok(MicrovmState { @@ -741,7 +736,7 @@ impl Vmm { pub fn update_balloon_config(&mut self, amount_mib: u32) -> Result<(), BalloonError> { // The balloon cannot have a target size greater than the size of // the guest memory. - if u64::from(amount_mib) > mem_size_mib(self.guest_memory()) { + if u64::from(amount_mib) > mem_size_mib(&self.guest_memory) { return Err(BalloonError::TooManyPagesRequested); } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 9d245e64821..64292612a16 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -219,7 +219,7 @@ fn snapshot_memory_to_file( .map_err(|err| MemoryBackingFile("open", err))?; // Determine what size our total memory area is. - let mem_size_mib = mem_size_mib(vmm.guest_memory()); + let mem_size_mib = mem_size_mib(&vmm.guest_memory); let expected_size = mem_size_mib * 1024 * 1024; if file_existed { @@ -248,15 +248,15 @@ fn snapshot_memory_to_file( match snapshot_type { SnapshotType::Diff => { let dirty_bitmap = vmm.get_dirty_bitmap().map_err(DirtyBitmap)?; - vmm.guest_memory() + vmm.guest_memory .dump_dirty(&mut file, &dirty_bitmap) .map_err(Memory) } SnapshotType::Full => { - let dump_res = vmm.guest_memory().dump(&mut file).map_err(Memory); + let dump_res = vmm.guest_memory.dump(&mut file).map_err(Memory); if dump_res.is_ok() { vmm.reset_dirty_bitmap(); - vmm.guest_memory().reset_dirty(); + vmm.guest_memory.reset_dirty(); } dump_res @@ -272,7 +272,7 @@ fn snapshot_memory_to_file( .for_each_virtio_device(|_, _, _, dev| { let d = dev.lock().unwrap(); if d.is_activated() { - d.mark_queue_memory_dirty(vmm.guest_memory()) + d.mark_queue_memory_dirty(&vmm.guest_memory) } else { Ok(()) } @@ -747,7 +747,7 @@ mod tests { assert!(states.vsock_device.is_some()); assert!(states.balloon_device.is_some()); - let memory_state = vmm.guest_memory().describe(); + let memory_state = vmm.guest_memory.describe(); let vcpu_states = vec![VcpuState::default()]; #[cfg(target_arch = "aarch64")] let mpidrs = construct_kvm_mpidrs(&vcpu_states); From 2971a0f9f770b107c5bcdad40e0b1fb86b208363 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 14:10:24 +0000 Subject: [PATCH 428/464] refactor: move CpuConfiguration creation into itself Move manual creation of `CpuConfiguration` from `configure_system_for_boot` into `CpuConfiguration::new`. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 26 ++++++------------------- src/vmm/src/arch/x86_64/mod.rs | 14 +++----------- src/vmm/src/cpu_config/aarch64/mod.rs | 28 +++++++++++++++++++++++---- src/vmm/src/cpu_config/x86_64/mod.rs | 20 +++++++++++++++++-- 4 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index d74712b8ca1..003949b8632 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -27,8 +27,6 @@ use linux_loader::loader::{Cmdline, KernelLoader}; use vm_memory::GuestMemoryError; use self::gic::GICDevice; -use crate::arch::aarch64::regs::Aarch64RegisterVec; -use crate::arch::aarch64::vcpu::{VcpuArchError, get_registers}; use crate::arch::{BootProtocol, DeviceType, EntryPoint}; use crate::cpu_config::aarch64::{CpuConfiguration, CpuConfigurationError}; use crate::cpu_config::templates::CustomCpuTemplate; @@ -51,14 +49,12 @@ pub enum ConfigurationError { KernelFile, /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} KernelLoader(#[from] linux_loader::loader::Error), - /// Error initializing the vcpu: {0} - VcpuInit(KvmVcpuError), - /// Error configuring the vcpu: {0} - VcpuConfigure(KvmVcpuError), - /// Error reading vcpu registers: {0} - VcpuGetRegs(VcpuArchError), + /// Error creating vcpu configuration: {0} + VcpuConfig(CpuConfigurationError), /// Error applying vcpu template: {0} VcpuApplyTemplate(CpuConfigurationError), + /// Error configuring the vcpu: {0} + VcpuConfigure(KvmVcpuError), } /// The start of the memory area reserved for MMIO devices. @@ -84,18 +80,8 @@ pub fn configure_system_for_boot( boot_cmdline: Cmdline, ) -> Result<(), ConfigurationError> { // Construct the base CpuConfiguration to apply CPU template onto. - let cpu_config = { - for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .init(&cpu_template.vcpu_features) - .map_err(ConfigurationError::VcpuInit)?; - } - - let mut regs = Aarch64RegisterVec::default(); - get_registers(&vcpus[0].kvm_vcpu.fd, &cpu_template.reg_list(), &mut regs) - .map_err(ConfigurationError::VcpuGetRegs)?; - CpuConfiguration { regs } - }; + let cpu_config = + CpuConfiguration::new(cpu_template, vcpus).map_err(ConfigurationError::VcpuConfig)?; // Apply CPU template to the base CpuConfiguration. let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template) diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 4f0707068b1..401aa95afc8 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -48,7 +48,7 @@ use super::EntryPoint; use crate::acpi::create_acpi_tables; use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; -use crate::cpu_config::x86_64::{CpuConfiguration, cpuid}; +use crate::cpu_config::x86_64::CpuConfiguration; use crate::device_manager::resources::ResourceAllocator; use crate::initrd::InitrdConfig; use crate::utils::{mib_to_bytes, u64_to_usize}; @@ -153,16 +153,8 @@ pub fn configure_system_for_boot( boot_cmdline: Cmdline, ) -> Result<(), ConfigurationError> { // Construct the base CpuConfiguration to apply CPU template onto. - let cpu_config = { - let cpuid = cpuid::Cpuid::try_from(vmm.kvm.supported_cpuid.clone()) - .map_err(GuestConfigError::CpuidFromKvmCpuid)?; - let msrs = vcpus[0] - .kvm_vcpu - .get_msrs(cpu_template.msr_index_iter()) - .map_err(GuestConfigError::VcpuIoctl)?; - CpuConfiguration { cpuid, msrs } - }; - + let cpu_config = + CpuConfiguration::new(vmm.kvm.supported_cpuid.clone(), cpu_template, &vcpus[0])?; // Apply CPU template to the base CpuConfiguration. let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template)?; diff --git a/src/vmm/src/cpu_config/aarch64/mod.rs b/src/vmm/src/cpu_config/aarch64/mod.rs index 26ca48572ac..c5459759583 100644 --- a/src/vmm/src/cpu_config/aarch64/mod.rs +++ b/src/vmm/src/cpu_config/aarch64/mod.rs @@ -9,13 +9,19 @@ pub mod static_cpu_templates; pub mod test_utils; use super::templates::CustomCpuTemplate; +use crate::Vcpu; use crate::arch::aarch64::regs::{Aarch64RegisterVec, RegSize}; -use crate::arch::aarch64::vcpu::VcpuArchError; +use crate::arch::aarch64::vcpu::{VcpuArchError, get_registers}; +use crate::vstate::vcpu::KvmVcpuError; /// Errors thrown while configuring templates. -#[derive(Debug, PartialEq, Eq, thiserror::Error)] -#[error("Failed to create a guest cpu configuration: {0}")] -pub struct CpuConfigurationError(#[from] pub VcpuArchError); +#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] +pub enum CpuConfigurationError { + /// Error initializing the vcpu: {0} + VcpuInit(#[from] KvmVcpuError), + /// Error reading vcpu registers: {0} + VcpuGetRegs(#[from] VcpuArchError), +} /// CPU configuration for aarch64 #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -25,6 +31,20 @@ pub struct CpuConfiguration { } impl CpuConfiguration { + /// Create new CpuConfiguration. + pub fn new( + cpu_template: &CustomCpuTemplate, + vcpus: &mut [Vcpu], + ) -> Result { + for vcpu in vcpus.iter_mut() { + vcpu.kvm_vcpu.init(&cpu_template.vcpu_features)?; + } + + let mut regs = Aarch64RegisterVec::default(); + get_registers(&vcpus[0].kvm_vcpu.fd, &cpu_template.reg_list(), &mut regs)?; + Ok(CpuConfiguration { regs }) + } + /// Creates new guest CPU config based on the provided template pub fn apply_template( mut self, diff --git a/src/vmm/src/cpu_config/x86_64/mod.rs b/src/vmm/src/cpu_config/x86_64/mod.rs index 3a26c621194..ddf0b64dea0 100644 --- a/src/vmm/src/cpu_config/x86_64/mod.rs +++ b/src/vmm/src/cpu_config/x86_64/mod.rs @@ -12,8 +12,11 @@ pub mod test_utils; use std::collections::BTreeMap; +use kvm_bindings::CpuId; + use self::custom_cpu_template::CpuidRegister; use super::templates::CustomCpuTemplate; +use crate::Vcpu; use crate::cpu_config::x86_64::cpuid::{Cpuid, CpuidKey}; /// Errors thrown while configuring templates. @@ -24,9 +27,9 @@ pub enum CpuConfigurationError { /// Template changes an MSR entry not supported by KVM: Register Address: {0:0x} MsrNotSupported(u32), /// Can create cpuid from raw: {0} - CpuidFromKvmCpuid(crate::cpu_config::x86_64::cpuid::CpuidTryFromKvmCpuid), + CpuidFromKvmCpuid(#[from] crate::cpu_config::x86_64::cpuid::CpuidTryFromKvmCpuid), /// KVM vcpu ioctl failed: {0} - VcpuIoctl(crate::vstate::vcpu::KvmVcpuError), + VcpuIoctl(#[from] crate::vstate::vcpu::KvmVcpuError), } /// CPU configuration for x86_64 CPUs @@ -41,6 +44,19 @@ pub struct CpuConfiguration { } impl CpuConfiguration { + /// Create new CpuConfiguration. + pub fn new( + supported_cpuid: CpuId, + cpu_template: &CustomCpuTemplate, + first_vcpu: &Vcpu, + ) -> Result { + let cpuid = cpuid::Cpuid::try_from(supported_cpuid)?; + let msrs = first_vcpu + .kvm_vcpu + .get_msrs(cpu_template.msr_index_iter())?; + Ok(CpuConfiguration { cpuid, msrs }) + } + /// Modifies provided config with changes from template pub fn apply_template( self, From 4c83038f53e515090466fe02a5a459b19ba72327 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 14:13:28 +0000 Subject: [PATCH 429/464] refactor(aarch64): remove Result type from `apply_template` On aarch64 `apply_template` cannot fail, so no reason for `Result` return type. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 10 +++------- src/vmm/src/cpu_config/aarch64/mod.rs | 7 ++----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 003949b8632..d54238839ca 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -50,9 +50,7 @@ pub enum ConfigurationError { /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} KernelLoader(#[from] linux_loader::loader::Error), /// Error creating vcpu configuration: {0} - VcpuConfig(CpuConfigurationError), - /// Error applying vcpu template: {0} - VcpuApplyTemplate(CpuConfigurationError), + VcpuConfig(#[from] CpuConfigurationError), /// Error configuring the vcpu: {0} VcpuConfigure(KvmVcpuError), } @@ -80,12 +78,10 @@ pub fn configure_system_for_boot( boot_cmdline: Cmdline, ) -> Result<(), ConfigurationError> { // Construct the base CpuConfiguration to apply CPU template onto. - let cpu_config = - CpuConfiguration::new(cpu_template, vcpus).map_err(ConfigurationError::VcpuConfig)?; + let cpu_config = CpuConfiguration::new(cpu_template, vcpus)?; // Apply CPU template to the base CpuConfiguration. - let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template) - .map_err(ConfigurationError::VcpuApplyTemplate)?; + let cpu_config = CpuConfiguration::apply_template(cpu_config, cpu_template); let vcpu_config = VcpuConfig { vcpu_count: machine_config.vcpu_count, diff --git a/src/vmm/src/cpu_config/aarch64/mod.rs b/src/vmm/src/cpu_config/aarch64/mod.rs index c5459759583..786183f3988 100644 --- a/src/vmm/src/cpu_config/aarch64/mod.rs +++ b/src/vmm/src/cpu_config/aarch64/mod.rs @@ -46,10 +46,7 @@ impl CpuConfiguration { } /// Creates new guest CPU config based on the provided template - pub fn apply_template( - mut self, - template: &CustomCpuTemplate, - ) -> Result { + pub fn apply_template(mut self, template: &CustomCpuTemplate) -> Self { for (modifier, mut reg) in template.reg_modifiers.iter().zip(self.regs.iter_mut()) { match reg.size() { RegSize::U32 => { @@ -70,7 +67,7 @@ impl CpuConfiguration { _ => unreachable!("Only 32, 64 and 128 bit wide registers are supported"), } } - Ok(self) + self } /// Returns ids of registers that are changed From c98f80169b342c0ee53c078479ac91e5ed6b2799 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 14:45:29 +0000 Subject: [PATCH 430/464] refactor: inline `configure_system` into `configure_system_for_boot` There is no reason to have these functions separately, so merge them. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 38 ++------- src/vmm/src/arch/x86_64/mod.rs | 137 ++++++++------------------------ 2 files changed, 40 insertions(+), 135 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index d54238839ca..8e6ba38089b 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -17,8 +17,6 @@ pub mod vcpu; pub mod vm; use std::cmp::min; -use std::collections::HashMap; -use std::ffi::CString; use std::fmt::Debug; use std::fs::File; @@ -26,12 +24,9 @@ use linux_loader::loader::pe::PE as Loader; use linux_loader::loader::{Cmdline, KernelLoader}; use vm_memory::GuestMemoryError; -use self::gic::GICDevice; -use crate::arch::{BootProtocol, DeviceType, EntryPoint}; +use crate::arch::{BootProtocol, EntryPoint}; use crate::cpu_config::aarch64::{CpuConfiguration, CpuConfigurationError}; use crate::cpu_config::templates::CustomCpuTemplate; -use crate::device_manager::mmio::MMIODeviceInfo; -use crate::devices::acpi::vmgenid::VmGenId; use crate::initrd::InitrdConfig; use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; @@ -108,41 +103,22 @@ pub fn configure_system_for_boot( let cmdline = boot_cmdline .as_cstring() .expect("Cannot create cstring from cmdline string"); - configure_system( + + let fdt = fdt::create_fdt( &vmm.guest_memory, - cmdline, vcpu_mpidr, + cmdline, vmm.mmio_device_manager.get_device_info(), vmm.vm.get_irqchip(), &vmm.acpi_device_manager.vmgenid, initrd, )?; - Ok(()) -} -/// Configures the system and should be called once per vm before starting vcpu threads. -fn configure_system( - guest_mem: &GuestMemoryMmap, - cmdline_cstring: CString, - vcpu_mpidr: Vec, - device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>, - gic_device: &GICDevice, - vmgenid: &Option, - initrd: &Option, -) -> Result<(), ConfigurationError> { - let fdt = fdt::create_fdt( - guest_mem, - vcpu_mpidr, - cmdline_cstring, - device_info, - gic_device, - vmgenid, - initrd, - )?; - let fdt_address = GuestAddress(get_fdt_addr(guest_mem)); - guest_mem + let fdt_address = GuestAddress(get_fdt_addr(&vmm.guest_memory)); + vmm.guest_memory .write_slice(fdt.as_slice(), fdt_address) .map_err(ConfigurationError::MemoryError)?; + Ok(()) } diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 401aa95afc8..9f54261b76b 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -33,6 +33,7 @@ pub mod generated; use std::fs::File; +use layout::CMDLINE_START; use linux_loader::configurator::linux::LinuxBootConfigurator; use linux_loader::configurator::pvh::PvhBootConfigurator; use linux_loader::configurator::{BootConfigurator, BootParams}; @@ -49,7 +50,6 @@ use crate::acpi::create_acpi_tables; use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; use crate::cpu_config::x86_64::CpuConfiguration; -use crate::device_manager::resources::ResourceAllocator; use crate::initrd::InitrdConfig; use crate::utils::{mib_to_bytes, u64_to_usize}; use crate::vmm_config::machine_config::MachineConfig; @@ -183,15 +183,28 @@ pub fn configure_system_for_boot( &boot_cmdline, ) .map_err(ConfigurationError::LoadCommandline)?; - configure_system( + + // Note that this puts the mptable at the last 1k of Linux's 640k base RAM + mptable::setup_mptable( &vmm.guest_memory, &mut vmm.resource_allocator, - GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), - cmdline_size, - initrd, vcpu_config.vcpu_count, - entry_point.protocol, - )?; + ) + .map_err(ConfigurationError::MpTableSetup)?; + + match entry_point.protocol { + BootProtocol::PvhBoot => { + configure_pvh(&vmm.guest_memory, GuestAddress(CMDLINE_START), initrd)?; + } + BootProtocol::LinuxBoot => { + configure_64bit_boot( + &vmm.guest_memory, + GuestAddress(CMDLINE_START), + cmdline_size, + initrd, + )?; + } + } // Create ACPI tables and write them in guest memory // For the time being we only support ACPI in x86_64 @@ -205,32 +218,6 @@ pub fn configure_system_for_boot( Ok(()) } -/// Configures the system and should be called once per vm before starting vcpu threads. -fn configure_system( - guest_mem: &GuestMemoryMmap, - resource_allocator: &mut ResourceAllocator, - cmdline_addr: GuestAddress, - cmdline_size: usize, - initrd: &Option, - num_cpus: u8, - boot_prot: BootProtocol, -) -> Result<(), ConfigurationError> { - // Note that this puts the mptable at the last 1k of Linux's 640k base RAM - mptable::setup_mptable(guest_mem, resource_allocator, num_cpus) - .map_err(ConfigurationError::MpTableSetup)?; - - match boot_prot { - BootProtocol::PvhBoot => { - configure_pvh(guest_mem, cmdline_addr, initrd)?; - } - BootProtocol::LinuxBoot => { - configure_64bit_boot(guest_mem, cmdline_addr, cmdline_size, initrd)?; - } - } - - Ok(()) -} - fn configure_pvh( guest_mem: &GuestMemoryMmap, cmdline_addr: GuestAddress, @@ -472,6 +459,7 @@ mod tests { use linux_loader::loader::bootparam::boot_e820_entry; use super::*; + use crate::device_manager::resources::ResourceAllocator; use crate::test_utils::{arch_mem, single_region_mem}; #[test] @@ -495,94 +483,35 @@ mod tests { let no_vcpus = 4; let gm = single_region_mem(0x10000); let mut resource_allocator = ResourceAllocator::new().unwrap(); - let config_err = configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - 1, - BootProtocol::LinuxBoot, - ); + let err = mptable::setup_mptable(&gm, &mut resource_allocator, 1); assert!(matches!( - config_err.unwrap_err(), - super::ConfigurationError::MpTableSetup(mptable::MptableError::NotEnoughMemory) + err.unwrap_err(), + mptable::MptableError::NotEnoughMemory )); // Now assigning some memory that falls before the 32bit memory hole. let mem_size = mib_to_bytes(128); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::LinuxBoot, - ) - .unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::PvhBoot, - ) - .unwrap(); + mptable::setup_mptable(&gm, &mut resource_allocator, no_vcpus).unwrap(); + configure_64bit_boot(&gm, GuestAddress(0), 0, &None).unwrap(); + configure_pvh(&gm, GuestAddress(0), &None).unwrap(); // Now assigning some memory that is equal to the start of the 32bit memory hole. let mem_size = mib_to_bytes(3328); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::LinuxBoot, - ) - .unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::PvhBoot, - ) - .unwrap(); + mptable::setup_mptable(&gm, &mut resource_allocator, no_vcpus).unwrap(); + configure_64bit_boot(&gm, GuestAddress(0), 0, &None).unwrap(); + configure_pvh(&gm, GuestAddress(0), &None).unwrap(); // Now assigning some memory that falls after the 32bit memory hole. let mem_size = mib_to_bytes(3330); let gm = arch_mem(mem_size); let mut resource_allocator = ResourceAllocator::new().unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::LinuxBoot, - ) - .unwrap(); - configure_system( - &gm, - &mut resource_allocator, - GuestAddress(0), - 0, - &None, - no_vcpus, - BootProtocol::PvhBoot, - ) - .unwrap(); + mptable::setup_mptable(&gm, &mut resource_allocator, no_vcpus).unwrap(); + configure_64bit_boot(&gm, GuestAddress(0), 0, &None).unwrap(); + configure_pvh(&gm, GuestAddress(0), &None).unwrap(); } #[test] From 6595eeb0504c4d5f05a825a417b970f5c8effd7c Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Tue, 25 Mar 2025 16:27:55 +0000 Subject: [PATCH 431/464] chore: remove unused `PartialEq` impl This is a dead code, so remove it. Signed-off-by: Egor Lazarchuk --- src/vmm/src/resources.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 2d472a3f3e2..837ddd91069 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -600,28 +600,6 @@ mod tests { } } - impl PartialEq for BootConfig { - fn eq(&self, other: &Self) -> bool { - self.cmdline.eq(&other.cmdline) - && self.kernel_file.metadata().unwrap().st_ino() - == other.kernel_file.metadata().unwrap().st_ino() - && self - .initrd_file - .as_ref() - .unwrap() - .metadata() - .unwrap() - .st_ino() - == other - .initrd_file - .as_ref() - .unwrap() - .metadata() - .unwrap() - .st_ino() - } - } - #[test] fn test_from_json() { let kernel_file = TempFile::new().unwrap(); From 03ee026fd30ff6ab769fee22de61fa643b562337 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 26 Mar 2025 10:48:04 +0000 Subject: [PATCH 432/464] refactor: add align_up and align_down functions Add `align_up` and `align_down` functions to stop reimplementing them in place all over the codebase. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 9 ++++++--- src/vmm/src/arch/x86_64/mod.rs | 8 +++++--- src/vmm/src/devices/virtio/test_utils.rs | 4 ++-- src/vmm/src/utils/mod.rs | 12 ++++++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 8e6ba38089b..983798dcf6a 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -28,6 +28,7 @@ use crate::arch::{BootProtocol, EntryPoint}; use crate::cpu_config::aarch64::{CpuConfiguration, CpuConfigurationError}; use crate::cpu_config::templates::CustomCpuTemplate; use crate::initrd::InitrdConfig; +use crate::utils::{align_up, usize_to_u64}; use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::KvmVcpuError; @@ -129,9 +130,11 @@ pub fn get_kernel_start() -> u64 { /// Returns the memory address where the initrd could be loaded. pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Option { - let round_to_pagesize = - |size| (size + (super::GUEST_PAGE_SIZE - 1)) & !(super::GUEST_PAGE_SIZE - 1); - match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) { + let rounded_size = align_up( + usize_to_u64(initrd_size), + usize_to_u64(super::GUEST_PAGE_SIZE), + ); + match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(rounded_size) { Some(offset) => { if guest_mem.address_in_range(offset) { Some(offset.raw_value()) diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 9f54261b76b..fdfce03b069 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -51,7 +51,7 @@ use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; use crate::cpu_config::x86_64::CpuConfiguration; use crate::initrd::InitrdConfig; -use crate::utils::{mib_to_bytes, u64_to_usize}; +use crate::utils::{align_down, mib_to_bytes, u64_to_usize, usize_to_u64}; use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{ Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, @@ -138,8 +138,10 @@ pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Opti return None; } - let align_to_pagesize = |address| address & !(super::GUEST_PAGE_SIZE - 1); - Some(align_to_pagesize(lowmem_size - initrd_size) as u64) + Some(align_down( + usize_to_u64(lowmem_size - initrd_size), + usize_to_u64(super::GUEST_PAGE_SIZE), + )) } /// Configures the system for booting Linux. diff --git a/src/vmm/src/devices/virtio/test_utils.rs b/src/vmm/src/devices/virtio/test_utils.rs index aa1ede08e58..8642d0a85f4 100644 --- a/src/vmm/src/devices/virtio/test_utils.rs +++ b/src/vmm/src/devices/virtio/test_utils.rs @@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use crate::devices::virtio::queue::Queue; use crate::test_utils::single_region_mem; -use crate::utils::u64_to_usize; +use crate::utils::{align_up, u64_to_usize}; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemoryMmap}; #[macro_export] @@ -250,7 +250,7 @@ impl<'a> VirtQueue<'a> { const USED_ALIGN: u64 = 4; let mut x = avail.end().0; - x = (x + USED_ALIGN - 1) & !(USED_ALIGN - 1); + x = align_up(x, USED_ALIGN); let used = VirtqUsed::new(GuestAddress(x), mem, qsize, u64_to_usize(USED_ALIGN)); diff --git a/src/vmm/src/utils/mod.rs b/src/vmm/src/utils/mod.rs index 9c81c7a3016..430f9fe9a71 100644 --- a/src/vmm/src/utils/mod.rs +++ b/src/vmm/src/utils/mod.rs @@ -53,3 +53,15 @@ pub const fn wrap_usize_to_u32(num: usize) -> Wrapping { pub const fn mib_to_bytes(mib: usize) -> usize { mib << MIB_TO_BYTES_SHIFT } + +/// Align address up to the aligment. +pub const fn align_up(addr: u64, align: u64) -> u64 { + debug_assert!(align != 0); + (addr + align - 1) & !(align - 1) +} + +/// Align address down to the aligment. +pub const fn align_down(addr: u64, align: u64) -> u64 { + debug_assert!(align != 0); + addr & !(align - 1) +} From 019dc6b32a1a64c86bf6b72ce7510ea92a48d6a6 Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Wed, 26 Mar 2025 11:49:29 +0000 Subject: [PATCH 433/464] refactor(aarch64): add `#[from]` to the arch error enum Remove `map_err` calls by adding `#[from]` to error variants. Signed-off-by: Egor Lazarchuk --- src/vmm/src/arch/aarch64/mod.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 983798dcf6a..10ffe53c8fa 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -40,7 +40,7 @@ pub enum ConfigurationError { /// Failed to create a Flattened Device Tree for this aarch64 microVM: {0} SetupFDT(#[from] fdt::FdtError), /// Failed to write to guest memory. - MemoryError(GuestMemoryError), + MemoryError(#[from] GuestMemoryError), /// Cannot copy kernel file fd KernelFile, /// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0} @@ -48,7 +48,7 @@ pub enum ConfigurationError { /// Error creating vcpu configuration: {0} VcpuConfig(#[from] CpuConfigurationError), /// Error configuring the vcpu: {0} - VcpuConfigure(KvmVcpuError), + VcpuConfigure(#[from] KvmVcpuError), } /// The start of the memory area reserved for MMIO devices. @@ -88,14 +88,12 @@ pub fn configure_system_for_boot( let optional_capabilities = vmm.kvm.optional_capabilities(); // Configure vCPUs with normalizing and setting the generated CPU configuration. for vcpu in vcpus.iter_mut() { - vcpu.kvm_vcpu - .configure( - &vmm.guest_memory, - entry_point, - &vcpu_config, - &optional_capabilities, - ) - .map_err(ConfigurationError::VcpuConfigure)?; + vcpu.kvm_vcpu.configure( + &vmm.guest_memory, + entry_point, + &vcpu_config, + &optional_capabilities, + )?; } let vcpu_mpidr = vcpus .iter_mut() @@ -116,9 +114,7 @@ pub fn configure_system_for_boot( )?; let fdt_address = GuestAddress(get_fdt_addr(&vmm.guest_memory)); - vmm.guest_memory - .write_slice(fdt.as_slice(), fdt_address) - .map_err(ConfigurationError::MemoryError)?; + vmm.guest_memory.write_slice(fdt.as_slice(), fdt_address)?; Ok(()) } From 3e4d83701e40802ddc42364eb5e86f3369b8af01 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 07:58:56 +0000 Subject: [PATCH 434/464] refactor: stop caching mpidr in struct KvmVcpu This cached field was only accessed precisely once, so the getter might as well compute it instead. While we're at it, merge the getting with the free-standing computation function. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/mod.rs | 3 ++- src/vmm/src/arch/aarch64/vcpu.rs | 39 +++++++++++--------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 10ffe53c8fa..e19f496f019 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -98,7 +98,8 @@ pub fn configure_system_for_boot( let vcpu_mpidr = vcpus .iter_mut() .map(|cpu| cpu.kvm_vcpu.get_mpidr()) - .collect(); + .collect::, _>>() + .map_err(KvmVcpuError::ConfigureRegisters)?; let cmdline = boot_cmdline .as_cstring() .expect("Cannot create cstring from cmdline string"); diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index a126ab1a3a5..5de35f97286 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -140,16 +140,6 @@ pub fn setup_boot_regs( Ok(()) } -/// Read the MPIDR - Multiprocessor Affinity Register. -pub fn get_mpidr(vcpufd: &VcpuFd) -> Result { - // MPIDR register is 64 bit wide on aarch64 - let mut mpidr = [0_u8; 8]; - match vcpufd.get_one_reg(MPIDR_EL1, &mut mpidr) { - Err(err) => Err(VcpuArchError::GetOneReg(MPIDR_EL1, err)), - Ok(_) => Ok(u64::from_le_bytes(mpidr)), - } -} - /// Saves the states of the system registers into `state`. /// /// # Arguments @@ -277,7 +267,6 @@ pub struct KvmVcpu { pub fd: VcpuFd, /// Vcpu peripherals, such as buses pub peripherals: Peripherals, - mpidr: u64, kvi: kvm_vcpu_init, } @@ -311,14 +300,18 @@ impl KvmVcpu { index, fd: kvm_vcpu, peripherals: Default::default(), - mpidr: 0, kvi, }) } - /// Gets the MPIDR register value. - pub fn get_mpidr(&self) -> u64 { - self.mpidr + /// Read the MPIDR - Multiprocessor Affinity Register. + pub fn get_mpidr(&self) -> Result { + // MPIDR register is 64 bit wide on aarch64 + let mut mpidr = [0_u8; 8]; + match self.fd.get_one_reg(MPIDR_EL1, &mut mpidr) { + Err(err) => Err(VcpuArchError::GetOneReg(MPIDR_EL1, err)), + Ok(_) => Ok(u64::from_le_bytes(mpidr)), + } } /// Configures an aarch64 specific vcpu for booting Linux. @@ -351,8 +344,6 @@ impl KvmVcpu { ) .map_err(KvmVcpuError::ConfigureRegisters)?; - self.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::ConfigureRegisters)?; - Ok(()) } @@ -393,7 +384,7 @@ impl KvmVcpu { ..Default::default() }; get_all_registers(&self.fd, &mut state.regs).map_err(KvmVcpuError::SaveState)?; - state.mpidr = get_mpidr(&self.fd).map_err(KvmVcpuError::SaveState)?; + state.mpidr = self.get_mpidr().map_err(KvmVcpuError::SaveState)?; state.kvi = self.kvi; // We don't save power off state in a snapshot, because @@ -757,21 +748,17 @@ mod tests { #[test] fn test_read_mpidr() { - let kvm = Kvm::new(vec![]).unwrap(); - let vm = kvm.fd.create_vm().unwrap(); - let vcpu = vm.create_vcpu(0).unwrap(); - let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + let (_, _, vcpu, _) = setup_vcpu(0x10000); // Must fail when vcpu is not initialized yet. - let res = get_mpidr(&vcpu); + let res = vcpu.get_mpidr(); assert!(matches!( res.unwrap_err(), VcpuArchError::GetOneReg(MPIDR_EL1, _) )); - vcpu.vcpu_init(&kvi).unwrap(); - assert_eq!(get_mpidr(&vcpu).unwrap(), 0x8000_0000); + vcpu.init_vcpu().unwrap(); + assert_eq!(vcpu.get_mpidr().unwrap(), 0x8000_0000); } #[test] From 9fc4073187fad4a7ff003f1f40fd7bb8ea04ec45 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 07:35:01 +0000 Subject: [PATCH 435/464] refactor: move get_manufacturer_id_from_host() to regs.rs Just make this a method on `Aarch64RegisterVec`, and make it return `Option`, because there was only a single error case, and the error message was additionall never displayed because the only call site ignores errors beyond acknowledging that they happened. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/regs.rs | 8 ++++++++ src/vmm/src/arch/aarch64/vcpu.rs | 16 ---------------- src/vmm/src/persist.rs | 12 ++++++------ 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/vmm/src/arch/aarch64/regs.rs b/src/vmm/src/arch/aarch64/regs.rs index d844fbfb56b..913f352a7d9 100644 --- a/src/vmm/src/arch/aarch64/regs.rs +++ b/src/vmm/src/arch/aarch64/regs.rs @@ -260,6 +260,14 @@ impl Aarch64RegisterVec { data: &mut self.data, } } + + /// Extract the Manufacturer ID from a VCPU state's registers. + /// The ID is found between bits 24-31 of MIDR_EL1 register. + pub fn manifacturer_id(&self) -> Option { + self.iter() + .find(|reg| reg.id == MIDR_EL1) + .map(|reg| ((reg.value::() >> 24) & 0xFF) as u32) + } } impl Serialize for Aarch64RegisterVec { diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 5de35f97286..2cbd2f702ab 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -45,22 +45,6 @@ pub enum VcpuArchError { GetMidrEl1(String), } -/// Extract the Manufacturer ID from a VCPU state's registers. -/// The ID is found between bits 24-31 of MIDR_EL1 register. -/// -/// # Arguments -/// -/// * `regs` - reference [`Aarch64RegisterVec`] structure with all registers of a VCPU. -pub fn get_manufacturer_id_from_state(regs: &Aarch64RegisterVec) -> Result { - let midr_el1 = regs.iter().find(|reg| reg.id == MIDR_EL1); - match midr_el1 { - Some(register) => Ok(((register.value::() >> 24) & 0xFF) as u32), - None => Err(VcpuArchError::GetMidrEl1( - "Failed to find MIDR_EL1 in vCPU state!".to_string(), - )), - } -} - /// Extract the Manufacturer ID from the host. /// The ID is found between bits 24-31 of MIDR_EL1 register. pub fn get_manufacturer_id_from_host() -> Result { diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 64292612a16..3ffc4355f0b 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -17,7 +17,7 @@ use userfaultfd::{FeatureFlags, Uffd, UffdBuilder}; use vmm_sys_util::sock_ctrl_msg::ScmSocket; #[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::vcpu::{get_manufacturer_id_from_host, get_manufacturer_id_from_state}; +use crate::arch::aarch64::vcpu::get_manufacturer_id_from_host; use crate::builder::{self, BuildMicrovmFromSnapshotError}; use crate::cpu_config::templates::StaticCpuTemplate; #[cfg(target_arch = "x86_64")] @@ -331,24 +331,24 @@ pub fn validate_cpu_vendor(microvm_state: &MicrovmState) { #[cfg(target_arch = "aarch64")] pub fn validate_cpu_manufacturer_id(microvm_state: &MicrovmState) { let host_cpu_id = get_manufacturer_id_from_host(); - let snapshot_cpu_id = get_manufacturer_id_from_state(µvm_state.vcpu_states[0].regs); + let snapshot_cpu_id = microvm_state.vcpu_states[0].regs.manifacturer_id(); match (host_cpu_id, snapshot_cpu_id) { - (Ok(host_id), Ok(snapshot_id)) => { + (Ok(host_id), Some(snapshot_id)) => { info!("Host CPU manufacturer ID: {host_id:?}"); info!("Snapshot CPU manufacturer ID: {snapshot_id:?}"); if host_id != snapshot_id { warn!("Host CPU manufacturer ID differs from the snapshotted one",); } } - (Ok(host_id), Err(_)) => { + (Ok(host_id), None) => { info!("Host CPU manufacturer ID: {host_id:?}"); warn!("Snapshot CPU manufacturer ID: couldn't get from the snapshot"); } - (Err(_), Ok(snapshot_id)) => { + (Err(_), Some(snapshot_id)) => { warn!("Host CPU manufacturer ID: couldn't get from the host"); info!("Snapshot CPU manufacturer ID: {snapshot_id:?}"); } - (Err(_), Err(_)) => { + (Err(_), None) => { warn!("Host CPU manufacturer ID: couldn't get from the host"); warn!("Snapshot CPU manufacturer ID: couldn't get from the snapshot"); } From e0db8f7305451aba7e9c5f3a340162ed60f45a70 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 09:56:07 +0000 Subject: [PATCH 436/464] refactor: move free functions into impl KvmVcpu block Almost all the free functions in arch::arch64::vcpu were just taking a vcpu reference as a first parameter (in some form). So just turn these into methods implemented on KvmVcpu that take &self. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/vcpu.rs | 350 +++++++++++++++---------------- 1 file changed, 170 insertions(+), 180 deletions(-) diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 2cbd2f702ab..82bbd499deb 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -62,80 +62,6 @@ pub fn get_manufacturer_id_from_host() -> Result { Ok(manufacturer_id >> 24) } -/// Configure relevant boot registers for a given vCPU. -/// -/// # Arguments -/// -/// * `cpu_id` - Index of current vcpu. -/// * `boot_ip` - Starting instruction pointer. -/// * `mem` - Reserved DRAM for current VM. -pub fn setup_boot_regs( - vcpufd: &VcpuFd, - cpu_id: u8, - boot_ip: u64, - mem: &GuestMemoryMmap, - optional_capabilities: &OptionalCapabilities, -) -> Result<(), VcpuArchError> { - let kreg_off = offset_of!(kvm_regs, regs); - - // Get the register index of the PSTATE (Processor State) register. - let pstate = offset_of!(user_pt_regs, pstate) + kreg_off; - let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate); - vcpufd - .set_one_reg(id, &PSTATE_FAULT_BITS_64.to_le_bytes()) - .map_err(|err| VcpuArchError::SetOneReg(id, err))?; - - // Other vCPUs are powered off initially awaiting PSCI wakeup. - if cpu_id == 0 { - // Setting the PC (Processor Counter) to the current program address (kernel address). - let pc = offset_of!(user_pt_regs, pc) + kreg_off; - let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pc); - vcpufd - .set_one_reg(id, &boot_ip.to_le_bytes()) - .map_err(|err| VcpuArchError::SetOneReg(id, err))?; - - // Last mandatory thing to set -> the address pointing to the FDT (also called DTB). - // "The device tree blob (dtb) must be placed on an 8-byte boundary and must - // not exceed 2 megabytes in size." -> https://www.kernel.org/doc/Documentation/arm64/booting.txt. - // We are choosing to place it the end of DRAM. See `get_fdt_addr`. - let regs0 = offset_of!(user_pt_regs, regs) + kreg_off; - let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0); - vcpufd - .set_one_reg(id, &get_fdt_addr(mem).to_le_bytes()) - .map_err(|err| VcpuArchError::SetOneReg(id, err))?; - - // Reset the physical counter for the guest. This way we avoid guest reading - // host physical counter. - // Resetting KVM_REG_ARM_PTIMER_CNT for single vcpu is enough because there is only - // one timer struct with offsets per VM. - // Because the access to KVM_REG_ARM_PTIMER_CNT is only present starting 6.4 kernel, - // we only do the reset if KVM_CAP_COUNTER_OFFSET is present as it was added - // in the same patch series as the ability to set the KVM_REG_ARM_PTIMER_CNT register. - // Path series which introduced the needed changes: - // https://lore.kernel.org/all/20230330174800.2677007-1-maz@kernel.org/ - // Note: the value observed by the guest will still be above 0, because there is a delta - // time between this resetting and first call to KVM_RUN. - if optional_capabilities.counter_offset { - vcpufd - .set_one_reg(KVM_REG_ARM_PTIMER_CNT, &[0; 8]) - .map_err(|err| VcpuArchError::SetOneReg(id, err))?; - } - } - Ok(()) -} - -/// Saves the states of the system registers into `state`. -/// -/// # Arguments -/// -/// * `regs` - Input/Output vector of registers. -pub fn get_all_registers( - vcpufd: &VcpuFd, - state: &mut Aarch64RegisterVec, -) -> Result<(), VcpuArchError> { - get_registers(vcpufd, &get_all_registers_ids(vcpufd)?, state) -} - /// Saves states of registers into `state`. /// /// # Arguments @@ -143,13 +69,13 @@ pub fn get_all_registers( /// * `ids` - Slice of registers ids to save. /// * `regs` - Input/Output vector of registers. pub fn get_registers( - vcpufd: &VcpuFd, + vcpu_fd: &VcpuFd, ids: &[u64], regs: &mut Aarch64RegisterVec, ) -> Result<(), VcpuArchError> { let mut big_reg = [0_u8; 256]; for id in ids.iter() { - let reg_size = vcpufd + let reg_size = vcpu_fd .get_one_reg(*id, &mut big_reg) .map_err(|e| VcpuArchError::GetOneReg(*id, e))?; let reg_ref = Aarch64RegisterRef::new(*id, &big_reg[0..reg_size]); @@ -158,66 +84,6 @@ pub fn get_registers( Ok(()) } -/// Returns all registers ids, including core and system -pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result, VcpuArchError> { - // Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are - // less than 500 registers expected, resize to the reported size when necessary. - let mut reg_list = RegList::new(500).map_err(VcpuArchError::Fam)?; - - match vcpufd.get_reg_list(&mut reg_list) { - Ok(_) => Ok(reg_list.as_slice().to_vec()), - Err(e) => match e.errno() { - libc::E2BIG => { - // resize and retry. - let size: usize = reg_list - .as_fam_struct_ref() - .n - .try_into() - // Safe to unwrap as Firecracker only targets 64-bit machines. - .unwrap(); - reg_list = RegList::new(size).map_err(VcpuArchError::Fam)?; - vcpufd - .get_reg_list(&mut reg_list) - .map_err(VcpuArchError::GetRegList)?; - - Ok(reg_list.as_slice().to_vec()) - } - _ => Err(VcpuArchError::GetRegList(e)), - }, - } -} - -/// Set the state of one system register. -/// -/// # Arguments -/// -/// * `reg` - Register to be set. -pub fn set_register(vcpufd: &VcpuFd, reg: Aarch64RegisterRef) -> Result<(), VcpuArchError> { - vcpufd - .set_one_reg(reg.id, reg.as_slice()) - .map_err(|e| VcpuArchError::SetOneReg(reg.id, e))?; - Ok(()) -} - -/// Get the multistate processor. -/// -/// # Arguments -/// -/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. -pub fn get_mpstate(vcpufd: &VcpuFd) -> Result { - vcpufd.get_mp_state().map_err(VcpuArchError::GetMp) -} - -/// Set the state of the system registers. -/// -/// # Arguments -/// -/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. -/// * `state` - Structure for returning the state of the system registers. -pub fn set_mpstate(vcpufd: &VcpuFd, state: kvm_mp_state) -> Result<(), VcpuArchError> { - vcpufd.set_mp_state(state).map_err(VcpuArchError::SetMp) -} - /// Errors associated with the wrappers over KVM ioctls. #[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)] pub enum KvmVcpuError { @@ -319,9 +185,7 @@ impl KvmVcpu { })?; } - setup_boot_regs( - &self.fd, - self.index, + self.setup_boot_regs( kernel_entry_point.entry_addr.raw_value(), guest_mem, optional_capabilities, @@ -364,10 +228,11 @@ impl KvmVcpu { /// Save the KVM internal state. pub fn save_state(&self) -> Result { let mut state = VcpuState { - mp_state: get_mpstate(&self.fd).map_err(KvmVcpuError::SaveState)?, + mp_state: self.get_mpstate().map_err(KvmVcpuError::SaveState)?, ..Default::default() }; - get_all_registers(&self.fd, &mut state.regs).map_err(KvmVcpuError::SaveState)?; + self.get_all_registers(&mut state.regs) + .map_err(KvmVcpuError::SaveState)?; state.mpidr = self.get_mpidr().map_err(KvmVcpuError::SaveState)?; state.kvi = self.kvi; @@ -393,7 +258,8 @@ impl KvmVcpu { .iter() .find(|reg| reg.id == KVM_REG_ARM64_SVE_VLS) { - set_register(&self.fd, sve_vls_reg).map_err(KvmVcpuError::RestoreState)?; + self.set_register(sve_vls_reg) + .map_err(KvmVcpuError::RestoreState)?; } self.finalize_vcpu()?; @@ -405,21 +271,21 @@ impl KvmVcpu { .iter() .filter(|reg| reg.id != KVM_REG_ARM64_SVE_VLS) { - set_register(&self.fd, reg).map_err(KvmVcpuError::RestoreState)?; + self.set_register(reg).map_err(KvmVcpuError::RestoreState)?; } - set_mpstate(&self.fd, state.mp_state).map_err(KvmVcpuError::RestoreState)?; + self.set_mpstate(state.mp_state) + .map_err(KvmVcpuError::RestoreState)?; Ok(()) } /// Dumps CPU configuration. pub fn dump_cpu_config(&self) -> Result { - let reg_list = get_all_registers_ids(&self.fd).map_err(KvmVcpuError::DumpCpuConfig)?; - let mut regs = Aarch64RegisterVec::default(); - get_registers(&self.fd, ®_list, &mut regs).map_err(KvmVcpuError::DumpCpuConfig)?; - + self.get_all_registers(&mut regs) + .map_err(KvmVcpuError::DumpCpuConfig)?; Ok(CpuConfiguration { regs }) } + /// Initializes internal vcpufd. fn init_vcpu(&self) -> Result<(), KvmVcpuError> { self.fd.vcpu_init(&self.kvi).map_err(KvmVcpuError::Init)?; @@ -437,6 +303,136 @@ impl KvmVcpu { } Ok(()) } + + /// Configure relevant boot registers for a given vCPU. + /// + /// # Arguments + /// + /// * `boot_ip` - Starting instruction pointer. + /// * `mem` - Reserved DRAM for current VM. + /// + `optional_capabilities` - which optional capabilities are enabled that might influence + /// vcpu configuration + pub fn setup_boot_regs( + &self, + boot_ip: u64, + mem: &GuestMemoryMmap, + optional_capabilities: &OptionalCapabilities, + ) -> Result<(), VcpuArchError> { + let kreg_off = offset_of!(kvm_regs, regs); + + // Get the register index of the PSTATE (Processor State) register. + let pstate = offset_of!(user_pt_regs, pstate) + kreg_off; + let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate); + self.fd + .set_one_reg(id, &PSTATE_FAULT_BITS_64.to_le_bytes()) + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; + + // Other vCPUs are powered off initially awaiting PSCI wakeup. + if self.index == 0 { + // Setting the PC (Processor Counter) to the current program address (kernel address). + let pc = offset_of!(user_pt_regs, pc) + kreg_off; + let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pc); + self.fd + .set_one_reg(id, &boot_ip.to_le_bytes()) + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; + + // Last mandatory thing to set -> the address pointing to the FDT (also called DTB). + // "The device tree blob (dtb) must be placed on an 8-byte boundary and must + // not exceed 2 megabytes in size." -> https://www.kernel.org/doc/Documentation/arm64/booting.txt. + // We are choosing to place it the end of DRAM. See `get_fdt_addr`. + let regs0 = offset_of!(user_pt_regs, regs) + kreg_off; + let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0); + self.fd + .set_one_reg(id, &get_fdt_addr(mem).to_le_bytes()) + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; + + // Reset the physical counter for the guest. This way we avoid guest reading + // host physical counter. + // Resetting KVM_REG_ARM_PTIMER_CNT for single vcpu is enough because there is only + // one timer struct with offsets per VM. + // Because the access to KVM_REG_ARM_PTIMER_CNT is only present starting 6.4 kernel, + // we only do the reset if KVM_CAP_COUNTER_OFFSET is present as it was added + // in the same patch series as the ability to set the KVM_REG_ARM_PTIMER_CNT register. + // Path series which introduced the needed changes: + // https://lore.kernel.org/all/20230330174800.2677007-1-maz@kernel.org/ + // Note: the value observed by the guest will still be above 0, because there is a delta + // time between this resetting and first call to KVM_RUN. + if optional_capabilities.counter_offset { + self.fd + .set_one_reg(KVM_REG_ARM_PTIMER_CNT, &[0; 8]) + .map_err(|err| VcpuArchError::SetOneReg(id, err))?; + } + } + Ok(()) + } + + /// Saves the states of the system registers into `state`. + /// + /// # Arguments + /// + /// * `regs` - Input/Output vector of registers. + pub fn get_all_registers(&self, state: &mut Aarch64RegisterVec) -> Result<(), VcpuArchError> { + get_registers(&self.fd, &self.get_all_registers_ids()?, state) + } + + /// Returns all registers ids, including core and system + pub fn get_all_registers_ids(&self) -> Result, VcpuArchError> { + // Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are + // less than 500 registers expected, resize to the reported size when necessary. + let mut reg_list = RegList::new(500).map_err(VcpuArchError::Fam)?; + + match self.fd.get_reg_list(&mut reg_list) { + Ok(_) => Ok(reg_list.as_slice().to_vec()), + Err(e) => match e.errno() { + libc::E2BIG => { + // resize and retry. + let size: usize = reg_list + .as_fam_struct_ref() + .n + .try_into() + // Safe to unwrap as Firecracker only targets 64-bit machines. + .unwrap(); + reg_list = RegList::new(size).map_err(VcpuArchError::Fam)?; + self.fd + .get_reg_list(&mut reg_list) + .map_err(VcpuArchError::GetRegList)?; + + Ok(reg_list.as_slice().to_vec()) + } + _ => Err(VcpuArchError::GetRegList(e)), + }, + } + } + + /// Set the state of one system register. + /// + /// # Arguments + /// + /// * `reg` - Register to be set. + pub fn set_register(&self, reg: Aarch64RegisterRef) -> Result<(), VcpuArchError> { + self.fd + .set_one_reg(reg.id, reg.as_slice()) + .map_err(|e| VcpuArchError::SetOneReg(reg.id, e))?; + Ok(()) + } + + /// Get the multistate processor. + /// + /// # Arguments + /// + /// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. + pub fn get_mpstate(&self) -> Result { + self.fd.get_mp_state().map_err(VcpuArchError::GetMp) + } + + /// Set the state of the system registers. + /// + /// # Arguments + /// + /// * `state` - Structure for returning the state of the system registers. + pub fn set_mpstate(&self, state: kvm_mp_state) -> Result<(), VcpuArchError> { + self.fd.set_mp_state(state).map_err(VcpuArchError::SetMp) + } } impl Peripherals { @@ -511,10 +507,15 @@ mod tests { use crate::vstate::vm::tests::setup_vm_with_memory; fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { - let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size); - let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); + let (kvm, mut vm, mut vcpu, vm_mem) = setup_vcpu_no_init(mem_size); vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); + (kvm, vm, vcpu, vm_mem) + } + + fn setup_vcpu_no_init(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { + let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size); + let vcpu = KvmVcpu::new(0, &vm).unwrap(); (kvm, vm, vcpu, vm_mem) } @@ -692,23 +693,20 @@ mod tests { #[test] fn test_setup_regs() { - let kvm = Kvm::new(vec![]).unwrap(); - let vm = kvm.fd.create_vm().unwrap(); - let vcpu = vm.create_vcpu(0).unwrap(); + let (kvm, _, vcpu, _) = setup_vcpu_no_init(0x10000); let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000); let optional_capabilities = kvm.optional_capabilities(); - let res = setup_boot_regs(&vcpu, 0, 0x0, &mem, &optional_capabilities); + let res = vcpu.setup_boot_regs(0x0, &mem, &optional_capabilities); assert!(matches!( res.unwrap_err(), VcpuArchError::SetOneReg(0x6030000000100042, _) )); - let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); - vcpu.vcpu_init(&kvi).unwrap(); + vcpu.init_vcpu().unwrap(); - setup_boot_regs(&vcpu, 0, 0x0, &mem, &optional_capabilities).unwrap(); + vcpu.setup_boot_regs(0x0, &mem, &optional_capabilities) + .unwrap(); // Check that the register is reset on compatible kernels. // Because there is a delta in time between we reset the register and time we @@ -716,7 +714,7 @@ mod tests { // small value. if optional_capabilities.counter_offset { let mut reg_bytes = [0_u8; 8]; - vcpu.get_one_reg(SYS_CNTPCT_EL0, &mut reg_bytes).unwrap(); + vcpu.fd.get_one_reg(SYS_CNTPCT_EL0, &mut reg_bytes).unwrap(); let counter_value = u64::from_le_bytes(reg_bytes); // We are reading the SYS_CNTPCT_EL0 right after resetting it. @@ -732,7 +730,7 @@ mod tests { #[test] fn test_read_mpidr() { - let (_, _, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu, _) = setup_vcpu_no_init(0x10000); // Must fail when vcpu is not initialized yet. let res = vcpu.get_mpidr(); @@ -740,28 +738,24 @@ mod tests { res.unwrap_err(), VcpuArchError::GetOneReg(MPIDR_EL1, _) )); - vcpu.init_vcpu().unwrap(); + assert_eq!(vcpu.get_mpidr().unwrap(), 0x8000_0000); } #[test] fn test_get_set_regs() { - let kvm = Kvm::new(vec![]).unwrap(); - let vm = kvm.fd.create_vm().unwrap(); - let vcpu = vm.create_vcpu(0).unwrap(); - let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + let (_, _, vcpu, _) = setup_vcpu_no_init(0x10000); // Must fail when vcpu is not initialized yet. let mut regs = Aarch64RegisterVec::default(); - let res = get_all_registers(&vcpu, &mut regs); + let res = vcpu.get_all_registers(&mut regs); assert!(matches!(res.unwrap_err(), VcpuArchError::GetRegList(_))); + vcpu.init_vcpu().unwrap(); - vcpu.vcpu_init(&kvi).unwrap(); - get_all_registers(&vcpu, &mut regs).unwrap(); + vcpu.get_all_registers(&mut regs).unwrap(); for reg in regs.iter() { - set_register(&vcpu, reg).unwrap(); + vcpu.set_register(reg).unwrap(); } } @@ -769,21 +763,17 @@ mod tests { fn test_mpstate() { use std::os::unix::io::AsRawFd; - let kvm = Kvm::new(vec![]).unwrap(); - let vm = kvm.fd.create_vm().unwrap(); - let vcpu = vm.create_vcpu(0).unwrap(); - let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + let (_, _, vcpu, _) = setup_vcpu(0x10000); - let res = get_mpstate(&vcpu); - set_mpstate(&vcpu, res.unwrap()).unwrap(); + let res = vcpu.get_mpstate(); + vcpu.set_mpstate(res.unwrap()).unwrap(); - unsafe { libc::close(vcpu.as_raw_fd()) }; + unsafe { libc::close(vcpu.fd.as_raw_fd()) }; - let res = get_mpstate(&vcpu); + let res = vcpu.get_mpstate(); assert!(matches!(res, Err(VcpuArchError::GetMp(_))), "{:?}", res); - let res = set_mpstate(&vcpu, kvm_mp_state::default()); + let res = vcpu.set_mpstate(kvm_mp_state::default()); assert!(matches!(res, Err(VcpuArchError::SetMp(_))), "{:?}", res); // dropping vcpu would double close the fd, so leak it From e94b72b8dae96f31da409882268fa2131b76bded Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 14:07:12 +0000 Subject: [PATCH 437/464] refactor: eliminate map_err from device registration in builder.rs Remove some more .map_err() noise in the mmio device registration code in builder.rs by using #[from] and returning more specialized error types. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 360b255be44..9b5924426a6 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -28,7 +28,7 @@ use crate::cpu_config::templates::{ use crate::device_manager::acpi::ACPIDeviceManager; #[cfg(target_arch = "x86_64")] use crate::device_manager::legacy::PortIODeviceManager; -use crate::device_manager::mmio::MMIODeviceManager; +use crate::device_manager::mmio::{MMIODeviceManager, MmioError}; use crate::device_manager::persist::{ ACPIDeviceManagerConstructorArgs, ACPIDeviceManagerRestoreError, MMIODevManagerConstructorArgs, }; @@ -590,9 +590,7 @@ fn attach_virtio_device( device: Arc>, cmdline: &mut LoaderKernelCmdline, is_vhost_user: bool, -) -> Result<(), StartMicrovmError> { - use self::StartMicrovmError::*; - +) -> Result<(), MmioError> { event_manager.add_subscriber(device.clone()); // The device mutex mustn't be locked here otherwise it will deadlock. @@ -605,21 +603,17 @@ fn attach_virtio_device( device, cmdline, ) - .map_err(RegisterMmioDevice) .map(|_| ()) } pub(crate) fn attach_boot_timer_device( vmm: &mut Vmm, request_ts: TimestampUs, -) -> Result<(), StartMicrovmError> { - use self::StartMicrovmError::*; - +) -> Result<(), MmioError> { let boot_timer = crate::devices::pseudo::BootTimer::new(request_ts); vmm.mmio_device_manager - .register_mmio_boot_timer(&mut vmm.resource_allocator, boot_timer) - .map_err(RegisterMmioDevice)?; + .register_mmio_boot_timer(&mut vmm.resource_allocator, boot_timer)?; Ok(()) } @@ -640,7 +634,7 @@ fn attach_entropy_device( cmdline: &mut LoaderKernelCmdline, entropy_device: &Arc>, event_manager: &mut EventManager, -) -> Result<(), StartMicrovmError> { +) -> Result<(), MmioError> { let id = entropy_device .lock() .expect("Poisoned lock") @@ -710,7 +704,7 @@ fn attach_unixsock_vsock_device( cmdline: &mut LoaderKernelCmdline, unix_vsock: &Arc>>, event_manager: &mut EventManager, -) -> Result<(), StartMicrovmError> { +) -> Result<(), MmioError> { let id = String::from(unix_vsock.lock().expect("Poisoned lock").id()); // The device mutex mustn't be locked here otherwise it will deadlock. attach_virtio_device(event_manager, vmm, id, unix_vsock.clone(), cmdline, false) @@ -721,7 +715,7 @@ fn attach_balloon_device( cmdline: &mut LoaderKernelCmdline, balloon: &Arc>, event_manager: &mut EventManager, -) -> Result<(), StartMicrovmError> { +) -> Result<(), MmioError> { let id = String::from(balloon.lock().expect("Poisoned lock").id()); // The device mutex mustn't be locked here otherwise it will deadlock. attach_virtio_device(event_manager, vmm, id, balloon.clone(), cmdline, false) From f6fa622118590e31408948802be0f689da4f4ed0 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 27 Mar 2025 10:45:48 +0000 Subject: [PATCH 438/464] test(conftest): move (not copy) vm artifacts This is to keep free space in the /srv filesystem. Signed-off-by: Nikita Kalyazin --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 3b75a3fa596..bfc6c6cedd7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -337,7 +337,7 @@ def microvm_factory(request, record_property, results_dir, netns_factory): if not os.path.isfile(src): continue dst = uvm_data / item - shutil.copy(src, dst) + shutil.move(src, dst) console_data = uvm.console_data if console_data: uvm_data.joinpath("guest-console.log").write_text(console_data) From c63d1edc89a00eed68d92ee8e60dbb4f455bffb5 Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Thu, 27 Mar 2025 10:43:10 +0000 Subject: [PATCH 439/464] vmm: Disable WAITPKG If UMWEAIT/TPAUSE instructions are executed within a guest, a physical processor is put into an implementation-depedent optimized state. It may lead to an overhead of waking it up when scheduling another guest on it. See comment in code for more details. Signed-off-by: Takahiro Itazuri --- CHANGELOG.md | 5 +++ docs/cpu_templates/cpuid-normalization.md | 1 + .../x86_64/cpuid/intel/normalize.rs | 43 +++++++++++++++++++ ...rprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json | 2 +- ...erprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json | 2 +- 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc5abd81892..4ed5a75ef72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ and this project adheres to ### Changed +- [#5118](https://github.com/firecracker-microvm/firecracker/pull/5118): Cleared + WAITPKG CPUID bit in CPUID normalization. The feature enables a guest to put a + physical processor into an idle state, which is undesirable in a FaaS + environment since that is what the host wants to decide. + ### Deprecated - [#4948](https://github.com/firecracker-microvm/firecracker/pull/4948): diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index 6a15ff4a9e0..a42132b6a07 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -35,6 +35,7 @@ See also: [boot protocol settings](boot-protocol.md) | Disable frequency selection | 0x6 | - | ECX | 3 | | Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 | | Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 | +| Disable WAITPKG (UMONITOR / UMWAIT / TPAUSE) | 0x7 | 0x0 | ECX | 5 | | Disable performance monitoring | 0xa | - | all | all | | Fill v2 extended topology enumeration leaf | 0x1f | all | all | all | | Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | all | all | diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index 2e22134e882..fa5e6766635 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -194,6 +194,48 @@ impl super::IntelCpuid { set_bit(&mut leaf_7_0.result.ebx, 6, true); set_bit(&mut leaf_7_0.result.ebx, 13, true); + // CPUID.(EAX=07H,ECX=0):ECX[5] (Mnemonic: WAITPKG) + // + // WAITPKG indicates support of user wait instructions (UMONITOR, UMWAIT and TPAUSE). + // - UMONITOR arms address monitoring hardware that checks for store operations on the + // specified address range. + // - UMWAIT instructs the processor to enter an implementation-dependent optimized state + // (either a light-weight power/performance optimized state (C0.1 idle state) or an + // improved power/performance optimized state (C0.2 idle state)) while monitoring the + // address range specified in UMONITOR. The instruction wakes up when the time-stamp + // counter reaches or exceeds the implicit EDX:EAX 64-bit input value. + // - TPAUSE instructs the processor to enter an implementation-dependent optimized state. + // The instruction wakes up when the time-stamp counter reaches or exceeds the implict + // EDX:EAX 64-bit input value. + // + // These instructions may be executed at any privilege level. Even when UMWAIT/TPAUSE are + // executed within a guest, the *physical* processor enters the requested optimized state. + // See Intel SDM vol.3 for more details of the behavior of these instructions in VMX + // non-root operation. + // + // MONITOR/MWAIT instructions are the privileged variant of UMONITOR/UMWAIT and are + // unconditionally emulated as NOP by KVM. + // https://github.com/torvalds/linux/commit/87c00572ba05aa8c9db118da75c608f47eb10b9e + // + // When UMONITOR/UMWAIT/TPAUSE were initially introduced, KVM clears the WAITPKG CPUID bit + // in KVM_GET_SUPPORTED_CPUID by default, and KVM exposed them to guest only when VMM + // explicitly set the bit via KVM_SET_CPUID2 API. + // https://github.com/torvalds/linux/commit/e69e72faa3a0709dd23df6a4ca060a15e99168a1 + // However, since v5.8, if the processor supports "enable user wait and pause" in Intel VMX, + // KVM_GET_SUPPORTED_CPUID sets the bit to 1 to let VMM know that it is available. So if the + // returned value is passed to KVM_SET_CPUID2 API as it is, guests are able to execute them. + // https://github.com/torvalds/linux/commit/0abcc8f65cc23b65bc8d1614cc64b02b1641ed7c + // + // Similar to MONITOR/MWAIT, we disable the guest's WAITPKG in order to prevent a guest from + // executing those instructions and putting a physical processor to an idle state which may + // lead to an overhead of waking it up when scheduling another guest on it. By clearing the + // WAITPKG bit in KVM_SET_CPUID2 API, KVM does not set the "enable user wait and pause" bit + // (bit 26) of the secondary processor-based VM-execution control, which makes guests get + // #UD when attempting to executing those instructions. + // + // Note that the WAITPKG bit is reserved on AMD. + set_bit(&mut leaf_7_0.result.ecx, 5, false); + Ok(()) } @@ -419,6 +461,7 @@ mod tests { .unwrap(); assert!((leaf_7_0.result.ebx & (1 << 6)) > 0); assert!((leaf_7_0.result.ebx & (1 << 13)) > 0); + assert_eq!((leaf_7_0.result.ecx & (1 << 5)), 0); } #[test] diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json index 18006227938..67a3d76b1ab 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json @@ -275,7 +275,7 @@ }, { "register": "ecx", - "bitmap": "0b00011010010000010101111101101110" + "bitmap": "0b00011010010000010101111101001110" }, { "register": "edx", diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json index f4244459112..38855ec24cc 100644 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json +++ b/tests/data/cpu_template_helper/fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json @@ -275,7 +275,7 @@ }, { "register": "ecx", - "bitmap": "0b00011011010000010101111101101110" + "bitmap": "0b00011011010000010101111101001110" }, { "register": "edx", From 4f1b59c2bddcaa5ae0cf2d33023ee012c0b5cf3a Mon Sep 17 00:00:00 2001 From: Takahiro Itazuri Date: Fri, 28 Mar 2025 08:25:13 +0000 Subject: [PATCH 440/464] test: Add waitpkg to host-minus-guest features We disabled WAITPKG intentionally since it can put a physical processor into an implementation-depedent optimized state. So it should not exist in guest. Signed-off-by: Takahiro Itazuri --- .../functional/test_cpu_features_host_vs_guest.py | 3 +++ 1 file changed, 3 insertions(+) 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 e387018d6d2..4b66b077839 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 @@ -274,6 +274,9 @@ def test_host_vs_guest_cpu_features(uvm_plain_any): # is not enumerated on CPUID, instead detected by actually attempting to read from # MSR address 0x33 (MSR_MEMORY_CTRL in Intel SDM, MSR_TEST_CTRL in Linux kernel). "split_lock_detect", + # Firecracker disables WAITPKG in CPUID normalization. + # https://github.com/firecracker-microvm/firecracker/pull/5118 + "waitpkg", } # The following features are also not virtualized by KVM yet but are only supported on From b38ec335d4c2525b4e883fbd032a82bcbd3a964d Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Wed, 26 Mar 2025 17:15:05 +0000 Subject: [PATCH 441/464] fix(vmm/persist): do not close uffd socket We prevent Rust from closing the socket file descriptor to avoid a potential race condition between the mappings message and the connection shutdown. If the latter arrives at the UFFD handler first, the handler never sees the mappings. Signed-off-by: Nikita Kalyazin --- CHANGELOG.md | 4 ++++ src/vmm/src/persist.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed5a75ef72..0fc97cac00f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,10 @@ and this project adheres to the `SendCtrlAltDel` command not working for ACPI-enabled guest kernels, by dropping the i8042.nopnp argument from the default kernel command line Firecracker constructs. +- [#5122](https://github.com/firecracker-microvm/firecracker/pull/5122): Keep + the UFFD Unix domain socket open to prevent the race condition between the + guest memory mappings message and the shutdown event that was sometimes + causing arrival of an empty message on the UFFD handler side. ## [1.11.0] diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 3ffc4355f0b..067cb51896b 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -6,6 +6,7 @@ use std::fmt::Debug; use std::fs::{File, OpenOptions}; use std::io::{self, Write}; +use std::mem::forget; use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixStream; use std::path::Path; @@ -657,6 +658,11 @@ fn send_uffd_handshake( uffd.as_raw_fd(), )?; + // We prevent Rust from closing the socket file descriptor to avoid a potential race condition + // between the mappings message and the connection shutdown. If the latter arrives at the UFFD + // handler first, the handler never sees the mappings. + forget(socket); + Ok(()) } From d28f3805c100439fac3f6b1e387c174c7d1e5798 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 31 Mar 2025 16:18:38 +0100 Subject: [PATCH 442/464] fix(test): do not double copy snapshot memory in uffd tests The restore_from_snapshot function did not integrate well with uffd-based snapshot restore: Even if a UFFD path was specified, it still created a copy of the snapshot memory file inside the chroot, even though the UFFD handler set this up long ago in space_pf_handler. Fix this, and while we're at it, also remove the need for passing in uffd handler and snapshot file explicitly when using uffd-based restore, as the spawn_pf_handler sets the uffd_handler field of the microvm object, and can also easily be made to actually contain the snapshot from which page faults are being served. Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 44 +++++++++++-------- tests/framework/utils_uffd.py | 18 +++++--- .../integration_tests/functional/test_uffd.py | 10 ++--- .../performance/test_huge_pages.py | 16 +++---- 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index 45375cd9c61..d2ec89bf941 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -971,33 +971,43 @@ def snapshot_full(self, *, mem_path: str = "mem", vmstate_path="vmstate"): def restore_from_snapshot( self, - snapshot: Snapshot, + snapshot: Snapshot = None, resume: bool = False, - uffd_path: Path = None, rename_interfaces: dict = None, ): """Restore a snapshot""" - jailed_snapshot = snapshot.copy_to_chroot(Path(self.chroot())) + if self.uffd_handler is None: + assert ( + snapshot is not None + ), "snapshot file must be provided if no uffd handler is attached!" + + jailed_snapshot = snapshot.copy_to_chroot(Path(self.chroot())) + else: + jailed_snapshot = self.uffd_handler.snapshot + jailed_mem = Path("/") / jailed_snapshot.mem.name jailed_vmstate = Path("/") / jailed_snapshot.vmstate.name - snapshot_disks = [v for k, v in snapshot.disks.items()] + snapshot_disks = [v for k, v in jailed_snapshot.disks.items()] assert len(snapshot_disks) > 0, "Snapshot requires at least one disk." jailed_disks = [] for disk in snapshot_disks: jailed_disks.append(self.create_jailed_resource(disk)) - self.disks = snapshot.disks - self.ssh_key = snapshot.ssh_key + self.disks = jailed_snapshot.disks + self.ssh_key = jailed_snapshot.ssh_key # Create network interfaces. - for iface in snapshot.net_ifaces: + for iface in jailed_snapshot.net_ifaces: self.add_net_iface(iface, api=False) mem_backend = {"backend_type": "File", "backend_path": str(jailed_mem)} - if uffd_path is not None: - mem_backend = {"backend_type": "Uffd", "backend_path": str(uffd_path)} + if self.uffd_handler is not None: + mem_backend = { + "backend_type": "Uffd", + "backend_path": str(self.uffd_handler.socket_path), + } - for key, value in snapshot.meta.items(): + for key, value in jailed_snapshot.meta.items(): setattr(self, key, value) # Adjust things just in case self.kernel_file = Path(self.kernel_file) @@ -1020,12 +1030,12 @@ def restore_from_snapshot( self.api.snapshot_load.put( mem_backend=mem_backend, snapshot_path=str(jailed_vmstate), - enable_diff_snapshots=snapshot.is_diff, + enable_diff_snapshots=jailed_snapshot.is_diff, resume_vm=resume, **optional_kwargs, ) # This is not a "wait for boot", but rather a "VM still works after restoration" - if snapshot.net_ifaces and resume: + if jailed_snapshot.net_ifaces and resume: self.wait_for_ssh_up() return jailed_snapshot @@ -1162,18 +1172,14 @@ def build_n_from_snapshot( microvm = self.build() microvm.spawn() - uffd_path = None if uffd_handler_name is not None: - pf_handler = spawn_pf_handler( + spawn_pf_handler( microvm, uffd_handler(uffd_handler_name, binary_dir=self.binary_path), - snapshot.mem, + snapshot, ) - uffd_path = pf_handler.socket_path - snapshot_copy = microvm.restore_from_snapshot( - snapshot, resume=True, uffd_path=uffd_path - ) + snapshot_copy = microvm.restore_from_snapshot(snapshot, resume=True) yield microvm diff --git a/tests/framework/utils_uffd.py b/tests/framework/utils_uffd.py index a502003ff5f..b25ca6cd928 100644 --- a/tests/framework/utils_uffd.py +++ b/tests/framework/utils_uffd.py @@ -17,12 +17,14 @@ class UffdHandler: """Describe the UFFD page fault handler process.""" - def __init__(self, name, socket_path, mem_file, chroot_path, log_file_name): + def __init__( + self, name, socket_path, snapshot: "Snapshot", chroot_path, log_file_name + ): """Instantiate the handler process with arguments.""" self._proc = None self._handler_name = name self.socket_path = socket_path - self._mem_file = mem_file + self.snapshot = snapshot self._chroot = chroot_path self._log_file = log_file_name @@ -35,7 +37,11 @@ def spawn(self, uid, gid): chroot_log_file = Path("/") / self._log_file with open(chroot_log_file, "w", encoding="utf-8") as logfile: - args = [f"/{self._handler_name}", self.socket_path, self._mem_file] + args = [ + f"/{self._handler_name}", + self.socket_path, + self.snapshot.mem.name, + ] self._proc = subprocess.Popen( args, stdout=logfile, stderr=subprocess.STDOUT ) @@ -77,16 +83,16 @@ def __del__(self): self.proc.kill() -def spawn_pf_handler(vm, handler_path, mem_path): +def spawn_pf_handler(vm, handler_path, snapshot): """Spawn page fault handler process.""" # Copy snapshot memory file into chroot of microVM. - jailed_mem = vm.create_jailed_resource(mem_path) + jailed_snapshot = snapshot.copy_to_chroot(Path(vm.chroot())) # Copy the valid page fault binary into chroot of microVM. jailed_handler = vm.create_jailed_resource(handler_path) handler_name = os.path.basename(jailed_handler) uffd_handler = UffdHandler( - handler_name, SOCKET_PATH, jailed_mem, vm.chroot(), "uffd.log" + handler_name, SOCKET_PATH, jailed_snapshot, vm.chroot(), "uffd.log" ) uffd_handler.spawn(vm.jailer.uid, vm.jailer.gid) vm.uffd_handler = uffd_handler diff --git a/tests/integration_tests/functional/test_uffd.py b/tests/integration_tests/functional/test_uffd.py index 95819844f05..e003807d282 100644 --- a/tests/integration_tests/functional/test_uffd.py +++ b/tests/integration_tests/functional/test_uffd.py @@ -92,9 +92,9 @@ def test_valid_handler(uvm_plain, snapshot): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot.mem) + spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot) - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) + vm.restore_from_snapshot(resume=True) # Inflate balloon. vm.api.balloon.patch(amount_mib=200) @@ -125,15 +125,13 @@ def test_malicious_handler(uvm_plain, snapshot): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("malicious"), snapshot.mem) + spawn_pf_handler(vm, uffd_handler("malicious"), snapshot) # We expect Firecracker to freeze while resuming from a snapshot # due to the malicious handler's unavailability. try: with Timeout(seconds=30): - vm.restore_from_snapshot( - snapshot, resume=True, uffd_path=pf_handler.socket_path - ) + vm.restore_from_snapshot(resume=True) assert False, "Firecracker should freeze" except (TimeoutError, requests.exceptions.ReadTimeout): pass diff --git a/tests/integration_tests/performance/test_huge_pages.py b/tests/integration_tests/performance/test_huge_pages.py index 5839245ebd9..6015cf6032b 100644 --- a/tests/integration_tests/performance/test_huge_pages.py +++ b/tests/integration_tests/performance/test_huge_pages.py @@ -93,9 +93,9 @@ def test_hugetlbfs_snapshot(microvm_factory, guest_kernel_linux_5_10, rootfs): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot.mem) + spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot) - vm.restore_from_snapshot(snapshot, resume=True, uffd_path=pf_handler.socket_path) + vm.restore_from_snapshot(resume=True) check_hugetlbfs_in_use(vm.firecracker_pid, "/anon_hugepage") @@ -135,11 +135,9 @@ def test_hugetlbfs_diff_snapshot(microvm_factory, uvm_plain): vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot_merged.mem) + spawn_pf_handler(vm, uffd_handler("on_demand"), snapshot_merged) - vm.restore_from_snapshot( - snapshot_merged, resume=True, uffd_path=pf_handler.socket_path - ) + vm.restore_from_snapshot(resume=True) # Verify if the restored microvm works. @@ -195,12 +193,10 @@ def test_ept_violation_count( vm.spawn() # Spawn page fault handler process. - pf_handler = spawn_pf_handler(vm, uffd_handler("fault_all"), snapshot.mem) + spawn_pf_handler(vm, uffd_handler("fault_all"), snapshot) with ftrace_events("kvm:*"): - vm.restore_from_snapshot( - snapshot, resume=True, uffd_path=pf_handler.socket_path - ) + vm.restore_from_snapshot(resume=True) # Verify if guest can run commands, and also wake up the fast page fault helper to trigger page faults. vm.ssh.check_output(f"kill -s {signal.SIGUSR1} {pid}") From 85622c6ee02607bc63be02122266ba8014089a8a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 31 Mar 2025 16:25:45 +0100 Subject: [PATCH 443/464] test(build_n_from_snapshot): Delete snapshot n after iteration n+2 If build_n_from_snapshot is asked to build many snapshots incrementally, it doesn't clean up after itself properly: Each iteration ends by creating a new snapshot of the VM, and this snapshot is passed to iteration n+1. Here, a copy is created inside the new VMs chroot, and iteration n+1 ends by creating a new snapshot for iteration n+2, and deleting the copy of the snapshot inside the chroot. However, we never delete the snapshot created in iteration n, and so with each iteration more snapshots accumulate. Fix this by having the function delete the snapshot created in iteration n after iteration n+2 finished successfully. The idea here is that in case of failure, we will have the snapshot created in iteration n+1 (the one which caused a failure in n+2), and also the snapshot created in n (which was the last known snapshot to successfully go through a test iteration, namely iteration n+1). Signed-off-by: Patrick Roy --- tests/framework/microvm.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py index d2ec89bf941..9ee3c85b0bb 100644 --- a/tests/framework/microvm.py +++ b/tests/framework/microvm.py @@ -1158,7 +1158,7 @@ def build_from_snapshot(self, snapshot: Snapshot): def build_n_from_snapshot( self, - snapshot, + current_snapshot, nr_vms, *, uffd_handler_name=None, @@ -1168,6 +1168,7 @@ def build_n_from_snapshot( """A generator of `n` microvms restored, either all restored from the same given snapshot (incremental=False), or created by taking successive snapshots of restored VMs """ + last_snapshot = None for _ in range(nr_vms): microvm = self.build() microvm.spawn() @@ -1176,27 +1177,35 @@ def build_n_from_snapshot( spawn_pf_handler( microvm, uffd_handler(uffd_handler_name, binary_dir=self.binary_path), - snapshot, + current_snapshot, ) - snapshot_copy = microvm.restore_from_snapshot(snapshot, resume=True) + snapshot_copy = microvm.restore_from_snapshot(current_snapshot, resume=True) yield microvm if incremental: - new_snapshot = microvm.make_snapshot(snapshot.snapshot_type) + # When doing diff snapshots, we continuously overwrite the same base snapshot file from the first + # iteration in-place with successive snapshots, so don't delete it! + if last_snapshot is not None and not last_snapshot.is_diff: + last_snapshot.delete() - if snapshot.is_diff: - new_snapshot = new_snapshot.rebase_snapshot( - snapshot, use_snapshot_editor + next_snapshot = microvm.make_snapshot(current_snapshot.snapshot_type) + + if current_snapshot.is_diff: + next_snapshot = next_snapshot.rebase_snapshot( + current_snapshot, use_snapshot_editor ) - snapshot = new_snapshot + last_snapshot = current_snapshot + current_snapshot = next_snapshot microvm.kill() snapshot_copy.delete() - snapshot.delete() + if last_snapshot is not None and not last_snapshot.is_diff: + last_snapshot.delete() + current_snapshot.delete() def kill(self): """Clean up all built VMs""" From 05e788102f0f254de850ce10bec5943cecd48974 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 2 Apr 2025 07:09:23 +0100 Subject: [PATCH 444/464] remove empty line in Cargo.toml It was bothering me that there was an empty line. Signed-off-by: Patrick Roy --- src/vmm/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 1b941b86416..a651f869c5a 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -30,7 +30,6 @@ log = { version = "0.4.27", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } memfd = "0.6.3" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } - semver = { version = "1.0.26", features = ["serde"] } serde = { version = "1.0.219", features = ["derive", "rc"] } serde_json = "1.0.140" From 6fa2064e4f24d0201ac534299a2a98e44994b29e Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 2 Apr 2025 07:52:38 +0100 Subject: [PATCH 445/464] chore: update bincode to 2.0 Follow the official migration guide for upgrading with serde support, described in [1] [1]: https://github.com/bincode-org/bincode/blob/trunk/docs/migration_guide.md#migrating-with-serde Signed-off-by: Patrick Roy --- Cargo.lock | 27 ++++++- src/firecracker/examples/seccomp/jailer.rs | 2 +- src/firecracker/examples/seccomp/panic.rs | 2 +- src/firecracker/src/seccomp.rs | 12 +-- src/seccompiler/Cargo.toml | 2 +- src/seccompiler/src/lib.rs | 21 ++++- src/vmm/Cargo.toml | 2 +- src/vmm/src/mmds/token.rs | 63 ++++----------- src/vmm/src/seccomp.rs | 91 +++++++++------------- src/vmm/src/snapshot/mod.rs | 25 +++--- 10 files changed, 113 insertions(+), 134 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index daeb0822782..4794425d4a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,11 +171,22 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" -version = "1.3.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" dependencies = [ + "bincode_derive", "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", ] [[package]] @@ -1503,6 +1514,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "userfaultfd" version = "0.8.1" @@ -1585,6 +1602,12 @@ dependencies = [ "vmm-sys-util", ] +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "vm-allocator" version = "0.1.1" diff --git a/src/firecracker/examples/seccomp/jailer.rs b/src/firecracker/examples/seccomp/jailer.rs index 62e4b84ea52..53822d377fa 100644 --- a/src/firecracker/examples/seccomp/jailer.rs +++ b/src/firecracker/examples/seccomp/jailer.rs @@ -13,7 +13,7 @@ fn main() { let bpf_path = &args[2]; let filter_file = File::open(bpf_path).unwrap(); - let map = deserialize_binary(&filter_file, None).unwrap(); + let map = deserialize_binary(&filter_file).unwrap(); // Loads filters. apply_filter(map.get("main").unwrap()).unwrap(); diff --git a/src/firecracker/examples/seccomp/panic.rs b/src/firecracker/examples/seccomp/panic.rs index 315899872f4..db0446cf882 100644 --- a/src/firecracker/examples/seccomp/panic.rs +++ b/src/firecracker/examples/seccomp/panic.rs @@ -11,7 +11,7 @@ fn main() { let filter_thread = &args[2]; let filter_file = File::open(bpf_path).unwrap(); - let map = deserialize_binary(&filter_file, None).unwrap(); + let map = deserialize_binary(&filter_file).unwrap(); apply_filter(map.get(filter_thread).unwrap()).unwrap(); panic!("Expected panic."); } diff --git a/src/firecracker/src/seccomp.rs b/src/firecracker/src/seccomp.rs index 22069def685..421220a7b5f 100644 --- a/src/firecracker/src/seccomp.rs +++ b/src/firecracker/src/seccomp.rs @@ -9,12 +9,6 @@ use vmm::seccomp::{BpfThreadMap, DeserializationError, deserialize_binary, get_e const THREAD_CATEGORIES: [&str; 3] = ["vmm", "api", "vcpu"]; -// This byte limit is passed to `bincode` to guard against a potential memory -// allocation DOS caused by binary filters that are too large. -// This limit can be safely determined since the maximum length of a BPF -// filter is 4096 instructions and Firecracker has a finite number of threads. -const DESERIALIZATION_BYTES_LIMIT: Option = Some(100_000); - /// Error retrieving seccomp filters. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum FilterError { @@ -72,15 +66,13 @@ pub fn get_filters(config: SeccompConfig) -> Result { fn get_default_filters() -> Result { // Retrieve, at compile-time, the serialized binary filter generated with seccompiler. let bytes: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/seccomp_filter.bpf")); - let map = deserialize_binary(bytes, DESERIALIZATION_BYTES_LIMIT) - .map_err(FilterError::Deserialization)?; + let map = deserialize_binary(bytes).map_err(FilterError::Deserialization)?; filter_thread_categories(map) } /// Retrieve custom seccomp filters. fn get_custom_filters(reader: R) -> Result { - let map = deserialize_binary(BufReader::new(reader), DESERIALIZATION_BYTES_LIMIT) - .map_err(FilterError::Deserialization)?; + let map = deserialize_binary(BufReader::new(reader)).map_err(FilterError::Deserialization)?; filter_thread_categories(map) } diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index 09472f8b45e..f1f67a47d7a 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -16,7 +16,7 @@ path = "src/bin.rs" bench = false [dependencies] -bincode = "1.2.1" +bincode = { version = "2.0.1", features = ["serde"] } clap = { version = "4.5.32", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.171" diff --git a/src/seccompiler/src/lib.rs b/src/seccompiler/src/lib.rs index 3fd62106275..ecd157c4449 100644 --- a/src/seccompiler/src/lib.rs +++ b/src/seccompiler/src/lib.rs @@ -8,7 +8,9 @@ use std::os::fd::{AsRawFd, FromRawFd}; use std::os::unix::fs::MetadataExt; use std::str::FromStr; -use bincode::Error as BincodeError; +use bincode::config; +use bincode::config::{Configuration, Fixint, Limit, LittleEndian}; +use bincode::error::EncodeError as BincodeError; mod bindings; use bindings::*; @@ -17,6 +19,18 @@ pub mod types; pub use types::*; use zerocopy::IntoBytes; +// This byte limit is passed to `bincode` to guard against a potential memory +// allocation DOS caused by binary filters that are too large. +// This limit can be safely determined since the maximum length of a BPF +// filter is 4096 instructions and Firecracker has a finite number of threads. +const DESERIALIZATION_BYTES_LIMIT: usize = 100_000; + +pub const BINCODE_CONFIG: Configuration> = + config::standard() + .with_fixed_int_encoding() + .with_limit::() + .with_little_endian(); + /// Binary filter compilation errors. #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum CompilationError { @@ -174,8 +188,9 @@ pub fn compile_bpf( bpf_map.insert(name.clone(), bpf); } - let output_file = File::create(out_path).map_err(CompilationError::OutputCreate)?; + let mut output_file = File::create(out_path).map_err(CompilationError::OutputCreate)?; - bincode::serialize_into(output_file, &bpf_map).map_err(CompilationError::BincodeSerialize)?; + bincode::encode_into_std_write(&bpf_map, &mut output_file, BINCODE_CONFIG) + .map_err(CompilationError::BincodeSerialize)?; Ok(()) } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index a651f869c5a..b566b2a8c91 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -14,7 +14,7 @@ aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } aws-lc-rs = { version = "1.12.6", features = ["bindgen"] } base64 = "0.22.1" -bincode = "1.2.1" +bincode = { version = "2.0.1", features = ["serde"] } bitflags = "2.9.0" crc64 = "2.0.0" derive_more = { version = "2.0.1", default-features = false, features = ["from", "display"] } diff --git a/src/vmm/src/mmds/token.rs b/src/vmm/src/mmds/token.rs index 64c65e9015d..e902303593d 100644 --- a/src/vmm/src/mmds/token.rs +++ b/src/vmm/src/mmds/token.rs @@ -10,7 +10,8 @@ use std::{fmt, io}; use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Nonce}; use base64::Engine; -use bincode::{DefaultOptions, Error as BincodeError, Options}; +use bincode::config; +use bincode::config::{Configuration, Fixint, Limit, LittleEndian}; use serde::{Deserialize, Serialize}; use utils::time::{ClockType, get_time_ms}; @@ -45,6 +46,12 @@ const TOKEN_LENGTH_LIMIT: usize = 70; /// too much memory when deserializing tokens. const DESERIALIZATION_BYTES_LIMIT: usize = std::mem::size_of::(); +const BINCODE_CONFIG: Configuration> = + config::standard() + .with_fixed_int_encoding() + .with_limit::() + .with_little_endian(); + #[rustfmt::skip] #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum MmdsTokenError { @@ -57,7 +64,7 @@ pub enum MmdsTokenError { /// Invalid time to live value provided for token: {0}. Please provide a value between {MIN_TOKEN_TTL_SECONDS:} and {MAX_TOKEN_TTL_SECONDS:}. InvalidTtlValue(u32), /// Bincode serialization failed: {0}. - Serialization(#[from] BincodeError), + Serialization(#[from] bincode::error::EncodeError), /// Failed to encrypt token. TokenEncryption, } @@ -287,7 +294,7 @@ impl Token { /// Encode token structure into a string using base64 encoding. fn base64_encode(&self) -> Result { - let token_bytes: Vec = bincode::serialize(self)?; + let token_bytes: Vec = bincode::serde::encode_to_vec(self, BINCODE_CONFIG)?; // Encode token structure bytes into base64. Ok(base64::engine::general_purpose::STANDARD.encode(token_bytes)) @@ -299,12 +306,9 @@ impl Token { .decode(encoded_token) .map_err(|_| MmdsTokenError::ExpiryExtraction)?; - let token: Token = DefaultOptions::new() - .with_fixint_encoding() - .allow_trailing_bytes() - .with_limit(DESERIALIZATION_BYTES_LIMIT as u64) - .deserialize(&token_bytes) - .map_err(|_| MmdsTokenError::ExpiryExtraction)?; + let token: Token = bincode::serde::decode_from_slice(&token_bytes, BINCODE_CONFIG) + .map_err(|_| MmdsTokenError::ExpiryExtraction)? + .0; Ok(token) } } @@ -518,45 +522,4 @@ mod tests { assert!(!token_authority.is_valid(&token0)); assert!(!token_authority.is_valid(&token1)); } - - #[test] - fn test_error_display() { - assert_eq!( - MmdsTokenError::EntropyPool(io::Error::from_raw_os_error(0)).to_string(), - format!( - "Failed to extract entropy from /dev/urandom entropy pool: {}.", - io::Error::from_raw_os_error(0) - ) - ); - - assert_eq!( - MmdsTokenError::ExpiryExtraction.to_string(), - "Failed to extract expiry value from token." - ); - - assert_eq!( - MmdsTokenError::InvalidState.to_string(), - "Invalid token authority state." - ); - - assert_eq!( - MmdsTokenError::InvalidTtlValue(0).to_string(), - format!( - "Invalid time to live value provided for token: 0. Please provide a value between \ - {} and {}.", - MIN_TOKEN_TTL_SECONDS, MAX_TOKEN_TTL_SECONDS - ) - ); - - assert_eq!( - MmdsTokenError::Serialization(BincodeError::new(bincode::ErrorKind::SizeLimit)) - .to_string(), - "Bincode serialization failed: the size limit has been reached." - ); - - assert_eq!( - MmdsTokenError::TokenEncryption.to_string(), - "Failed to encrypt token." - ); - } } diff --git a/src/vmm/src/seccomp.rs b/src/vmm/src/seccomp.rs index 3da974e6027..56e30908a62 100644 --- a/src/vmm/src/seccomp.rs +++ b/src/vmm/src/seccomp.rs @@ -5,7 +5,20 @@ use std::collections::HashMap; use std::io::Read; use std::sync::Arc; -use bincode::{DefaultOptions, Options}; +use bincode::config; +use bincode::config::{Configuration, Fixint, Limit, LittleEndian}; + +// This byte limit is passed to `bincode` to guard against a potential memory +// allocation DOS caused by binary filters that are too large. +// This limit can be safely determined since the maximum length of a BPF +// filter is 4096 instructions and Firecracker has a finite number of threads. +const DESERIALIZATION_BYTES_LIMIT: usize = 100_000; + +const BINCODE_CONFIG: Configuration> = + config::standard() + .with_fixed_int_encoding() + .with_limit::() + .with_little_endian(); /// Each BPF instruction is 8 bytes long and 4 byte aligned. /// This alignment needs to be satisfied in order for a BPF code to be accepted @@ -22,7 +35,7 @@ pub type BpfProgramRef<'a> = &'a [BpfInstruction]; pub type BpfThreadMap = HashMap>; /// Binary filter deserialization errors. -pub type DeserializationError = bincode::Error; +pub type DeserializationError = bincode::error::DecodeError; /// Retrieve empty seccomp filters. pub fn get_empty_filters() -> BpfThreadMap { @@ -34,19 +47,8 @@ pub fn get_empty_filters() -> BpfThreadMap { } /// Deserialize binary with bpf filters -pub fn deserialize_binary( - reader: R, - bytes_limit: Option, -) -> Result { - let result = match bytes_limit { - Some(limit) => DefaultOptions::new() - .with_fixint_encoding() - .allow_trailing_bytes() - .with_limit(limit) - .deserialize_from::>(reader), - // No limit is the default. - None => bincode::deserialize_from::>(reader), - }?; +pub fn deserialize_binary(mut reader: R) -> Result { + let result: HashMap = bincode::decode_from_std_read(&mut reader, BINCODE_CONFIG)?; Ok(result .into_iter() @@ -134,49 +136,28 @@ mod tests { #[test] fn test_deserialize_binary() { // Malformed bincode binary. - { - let data = "adassafvc".to_string(); - deserialize_binary(data.as_bytes(), None).unwrap_err(); - } + let data = "adassafvc".to_string(); + deserialize_binary(data.as_bytes()).unwrap_err(); // Test that the binary deserialization is correct, and that the thread keys // have been lowercased. - { - let bpf_prog = vec![0; 2]; - let mut filter_map: HashMap = HashMap::new(); - filter_map.insert("VcpU".to_string(), bpf_prog.clone()); - let bytes = bincode::serialize(&filter_map).unwrap(); - - let mut expected_res = BpfThreadMap::new(); - expected_res.insert("vcpu".to_string(), Arc::new(bpf_prog)); - assert_eq!(deserialize_binary(&bytes[..], None).unwrap(), expected_res); - } - - // Test deserialization with binary_limit. - { - let bpf_prog = vec![0; 2]; - - let mut filter_map: HashMap = HashMap::new(); - filter_map.insert("t1".to_string(), bpf_prog.clone()); - - let bytes = bincode::serialize(&filter_map).unwrap(); - - // Binary limit too low. - assert!(matches!( - deserialize_binary(&bytes[..], Some(20)).unwrap_err(), - error - if error.to_string() == "the size limit has been reached" - )); - - let mut expected_res = BpfThreadMap::new(); - expected_res.insert("t1".to_string(), Arc::new(bpf_prog)); - - // Correct binary limit. - assert_eq!( - deserialize_binary(&bytes[..], Some(50)).unwrap(), - expected_res - ); - } + let bpf_prog = vec![0; 2]; + let mut filter_map: HashMap = HashMap::new(); + filter_map.insert("VcpU".to_string(), bpf_prog.clone()); + let bytes = bincode::serde::encode_to_vec(&filter_map, BINCODE_CONFIG).unwrap(); + + let mut expected_res = BpfThreadMap::new(); + expected_res.insert("vcpu".to_string(), Arc::new(bpf_prog)); + assert_eq!(deserialize_binary(&bytes[..]).unwrap(), expected_res); + + let bpf_prog = vec![0; DESERIALIZATION_BYTES_LIMIT + 1]; + let mut filter_map: HashMap = HashMap::new(); + filter_map.insert("VcpU".to_string(), bpf_prog.clone()); + let bytes = bincode::serde::encode_to_vec(&filter_map, BINCODE_CONFIG).unwrap(); + assert!(matches!( + deserialize_binary(&bytes[..]).unwrap_err(), + bincode::error::DecodeError::LimitExceeded + )); } #[test] diff --git a/src/vmm/src/snapshot/mod.rs b/src/vmm/src/snapshot/mod.rs index a4900ee6eff..57ad3980215 100644 --- a/src/vmm/src/snapshot/mod.rs +++ b/src/vmm/src/snapshot/mod.rs @@ -28,19 +28,27 @@ mod persist; use std::fmt::Debug; use std::io::{Read, Write}; -use bincode::Options; +use bincode::config; +use bincode::config::{Configuration, Fixint, Limit, LittleEndian}; use semver::Version; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::snapshot::crc::{CRC64Reader, CRC64Writer}; pub use crate::snapshot::persist::Persist; +use crate::utils::mib_to_bytes; #[cfg(target_arch = "x86_64")] const SNAPSHOT_MAGIC_ID: u64 = 0x0710_1984_8664_0000u64; /// Constant bounding how much memory bincode may allocate during vmstate file deserialization -const VM_STATE_DESERIALIZE_LIMIT: u64 = 10_485_760; // 10MiB +const DESERIALIZATION_BYTES_LIMIT: usize = mib_to_bytes(10); + +const BINCODE_CONFIG: Configuration> = + config::standard() + .with_fixed_int_encoding() + .with_limit::() + .with_little_endian(); #[cfg(target_arch = "aarch64")] const SNAPSHOT_MAGIC_ID: u64 = 0x0710_1984_AAAA_0000u64; @@ -110,13 +118,7 @@ impl Snapshot { T: Read, O: DeserializeOwned + Debug, { - // flags below are those used by default by bincode::deserialize_from, plus `with_limit`. - bincode::DefaultOptions::new() - .with_limit(VM_STATE_DESERIALIZE_LIMIT) - .with_fixint_encoding() - .allow_trailing_bytes() // need this because we deserialize header and snapshot from the same file, so after - // reading the header, there will be trailing bytes. - .deserialize_from(reader) + bincode::serde::decode_from_std_read(reader, BINCODE_CONFIG) .map_err(|err| SnapshotError::Serde(err.to_string())) } @@ -126,7 +128,10 @@ impl Snapshot { T: Write, O: Serialize + Debug, { - bincode::serialize_into(writer, data).map_err(|err| SnapshotError::Serde(err.to_string())) + bincode::serde::encode_into_std_write(data, writer, BINCODE_CONFIG) + .map_err(|err| SnapshotError::Serde(err.to_string()))?; + + Ok(()) } /// Attempts to load an existing snapshot without performing CRC or version validation. From 1f1c5c0e6784073f9aa24fd009191334fd5bd581 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 12:05:58 +0000 Subject: [PATCH 446/464] build(deps): Bump the firecracker group across 1 directory with 8 updates Bumps the firecracker group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [clap](https://github.com/clap-rs/clap) | `4.5.32` | `4.5.35` | | [micro_http](https://github.com/firecracker-microvm/micro-http) | ``18f5b6f`` | ``e854e50`` | | [env_logger](https://github.com/rust-cli/env_logger) | `0.11.7` | `0.11.8` | | [aws-lc-rs](https://github.com/aws/aws-lc-rs) | `1.12.6` | `1.13.0` | | [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) | `0.13.4` | `0.13.5` | | [once_cell](https://github.com/matklad/once_cell) | `1.21.1` | `1.21.3` | Updates `clap` from 4.5.32 to 4.5.35 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.32...clap_complete-v4.5.35) Updates `micro_http` from `18f5b6f` to `e854e50` - [Commits](https://github.com/firecracker-microvm/micro-http/compare/18f5b6f5f5adbc553cb85f6a9c6c319ae9b0ec69...e854e50bc06a7e7bc0e5f5835d8f3f951e21f05f) Updates `env_logger` from 0.11.7 to 0.11.8 - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.7...v0.11.8) Updates `aws-lc-rs` from 1.12.6 to 1.13.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/v1.12.6...v1.13.0) Updates `aws-lc-fips-sys` from 0.13.4 to 0.13.5 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.4...aws-lc-fips-sys/v0.13.5) Updates `aws-lc-sys` from 0.27.1 to 0.28.0 - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-sys/v0.27.1...aws-lc-sys/v0.28.0) Updates `clap_builder` from 4.5.32 to 4.5.35 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.5.32...v4.5.35) Updates `once_cell` from 1.21.1 to 1.21.3 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.21.1...v1.21.3) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: micro_http dependency-type: direct:production dependency-group: firecracker - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-rs dependency-type: direct:production update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: aws-lc-fips-sys dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: aws-lc-sys dependency-type: indirect update-type: version-update:semver-minor dependency-group: firecracker - dependency-name: clap_builder dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker - dependency-name: once_cell dependency-type: indirect update-type: version-update:semver-patch dependency-group: firecracker ... Signed-off-by: dependabot[bot] --- Cargo.lock | 30 +++++++++++++++--------------- src/clippy-tracing/Cargo.toml | 2 +- src/cpu-template-helper/Cargo.toml | 2 +- src/log-instrument/Cargo.toml | 2 +- src/seccompiler/Cargo.toml | 2 +- src/snapshot-editor/Cargo.toml | 2 +- src/vmm/Cargo.toml | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4794425d4a0..79cc44a4567 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,9 +126,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-fips-sys" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6f97c07b7eb57063d9f62cbb5638bcdf699888f8e9febd07a88b156c4b05bb" +checksum = "2d9c2e952a1f57e8cbc78b058a968639e70c4ce8b9c0a5e6363d4e5670eed795" dependencies = [ "bindgen 0.69.5", "cc", @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.6" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" +checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" +checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" dependencies = [ "bindgen 0.69.5", "cc", @@ -342,9 +342,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", "clap_derive", @@ -361,9 +361,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -568,9 +568,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -966,7 +966,7 @@ dependencies = [ [[package]] name = "micro_http" version = "0.1.0" -source = "git+https://github.com/firecracker-microvm/micro-http#18f5b6f5f5adbc553cb85f6a9c6c319ae9b0ec69" +source = "git+https://github.com/firecracker-microvm/micro-http#e854e50bc06a7e7bc0e5f5835d8f3f951e21f05f" dependencies = [ "libc", "vmm-sys-util", @@ -1010,9 +1010,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index b3ecacfc49d..5d2fac82c7b 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.32", features = ["derive"] } +clap = { version = "4.5.35", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.94", features = ["span-locations"] } quote = "1.0.40" diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index c3838faab86..61536349d3f 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -10,7 +10,7 @@ name = "cpu-template-helper" bench = false [dependencies] -clap = { version = "4.5.32", features = ["derive", "string"] } +clap = { version = "4.5.35", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.171" log-instrument = { path = "../log-instrument", optional = true } diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index 39ae2ef6967..42489427841 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -32,7 +32,7 @@ log = "0.4.27" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] -env_logger = "0.11.7" +env_logger = "0.11.8" [lints] workspace = true diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index f1f67a47d7a..f9c06872fe3 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,7 +17,7 @@ bench = false [dependencies] bincode = { version = "2.0.1", features = ["serde"] } -clap = { version = "4.5.32", features = ["derive", "string"] } +clap = { version = "4.5.35", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.171" serde = { version = "1.0.219", features = ["derive"] } diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 106a4074501..64c7dfe2ce4 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -10,7 +10,7 @@ name = "snapshot-editor" bench = false [dependencies] -clap = { version = "4.5.32", features = ["derive", "string"] } +clap = { version = "4.5.35", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index b566b2a8c91..f0bf19edfc8 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -12,7 +12,7 @@ bench = false acpi_tables = { path = "../acpi-tables" } aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] } arrayvec = { version = "0.7.6", optional = true } -aws-lc-rs = { version = "1.12.6", features = ["bindgen"] } +aws-lc-rs = { version = "1.13.0", features = ["bindgen"] } base64 = "0.22.1" bincode = { version = "2.0.1", features = ["serde"] } bitflags = "2.9.0" From a6138aa8d45d9c64923df0e4ee9277a5dccfc947 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Thu, 27 Mar 2025 16:14:04 +0000 Subject: [PATCH 447/464] refactor(test): add helper function for creating mem in vhost tests The explicit calls to GuestMemoryMmap::create ended up being touched in like 5 of the following commits, so let's reduce the churn by putting it into a function. Signed-off-by: Patrick Roy --- .../devices/virtio/block/vhost_user/device.rs | 7 +++--- src/vmm/src/devices/virtio/vhost_user.rs | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/vmm/src/devices/virtio/block/vhost_user/device.rs b/src/vmm/src/devices/virtio/block/vhost_user/device.rs index c9907744080..b0bf5a31e3f 100644 --- a/src/vmm/src/devices/virtio/block/vhost_user/device.rs +++ b/src/vmm/src/devices/virtio/block/vhost_user/device.rs @@ -376,8 +376,9 @@ mod tests { use super::*; use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::devices::virtio::mmio::VIRTIO_MMIO_INT_CONFIG; + use crate::devices::virtio::vhost_user::tests::create_mem; use crate::test_utils::create_tmp_socket; - use crate::vstate::memory::{GuestAddress, GuestMemoryExtension}; + use crate::vstate::memory::GuestAddress; #[test] fn test_from_config() { @@ -778,9 +779,7 @@ mod tests { let file = TempFile::new().unwrap().into_file(); file.set_len(region_size as u64).unwrap(); let regions = vec![(GuestAddress(0x0), region_size)]; - let guest_memory = - GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) - .unwrap(); + let guest_memory = create_mem(file, ®ions); // During actiavion of the device features, memory and queues should be set and activated. vhost_block.activate(guest_memory).unwrap(); diff --git a/src/vmm/src/devices/virtio/vhost_user.rs b/src/vmm/src/devices/virtio/vhost_user.rs index 59efcb1a653..aebd46be648 100644 --- a/src/vmm/src/devices/virtio/vhost_user.rs +++ b/src/vmm/src/devices/virtio/vhost_user.rs @@ -459,15 +459,27 @@ impl VhostUserHandleImpl { } #[cfg(test)] -mod tests { +pub(crate) mod tests { #![allow(clippy::undocumented_unsafe_blocks)] + use std::fs::File; + use vmm_sys_util::tempfile::TempFile; use super::*; use crate::test_utils::create_tmp_socket; use crate::vstate::memory::{GuestAddress, GuestMemoryExtension}; + pub(crate) fn create_mem(file: File, regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap { + GuestMemoryMmap::create( + regions.iter().copied(), + libc::MAP_PRIVATE, + Some(file), + false, + ) + .unwrap() + } + #[test] fn test_new() { struct MockFrontend { @@ -763,9 +775,7 @@ mod tests { (GuestAddress(0x10000), region_size), ]; - let guest_memory = - GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) - .unwrap(); + let guest_memory = create_mem(file, ®ions); vuh.update_mem_table(&guest_memory).unwrap(); @@ -879,9 +889,7 @@ mod tests { file.set_len(region_size as u64).unwrap(); let regions = vec![(GuestAddress(0x0), region_size)]; - let guest_memory = - GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false) - .unwrap(); + let guest_memory = create_mem(file, ®ions); let mut queue = Queue::new(69); queue.initialize(&guest_memory).unwrap(); From 79b67fd29397b811bbad8707c1ea106de93717ad Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 31 Jan 2025 14:26:11 +0000 Subject: [PATCH 448/464] refactor: Have all memory creation method take similar arguments Have all of them operate on some sort of list of (GuestAddress, usize) tuples, for consistency. Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 3 ++- src/vmm/src/resources.rs | 6 +++--- src/vmm/src/vstate/memory.rs | 38 ++++++++++++++---------------------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 067cb51896b..0f640cd38b9 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -535,7 +535,8 @@ fn guest_memory_from_file( track_dirty_pages: bool, ) -> Result { let mem_file = File::open(mem_file_path)?; - let guest_mem = GuestMemoryMmap::snapshot_file(mem_file, mem_state, track_dirty_pages)?; + let guest_mem = + GuestMemoryMmap::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?; Ok(guest_mem) } diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 837ddd91069..57d5c2f7444 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -456,15 +456,15 @@ impl VmResources { // because that would require running a backend process. If in the future we converge to // a single way of backing guest memory for vhost-user and non-vhost-user cases, // that would not be worth the effort. + let regions = + crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib)); if vhost_user_device_used { GuestMemoryMmap::memfd_backed( - self.machine_config.mem_size_mib, + regions.as_ref(), self.machine_config.track_dirty_pages, self.machine_config.huge_pages, ) } else { - let regions = - crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib)); GuestMemoryMmap::anonymous( regions.into_iter(), self.machine_config.track_dirty_pages, diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 8875791f3a6..a5e1f9ba5e5 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -22,8 +22,7 @@ use vm_memory::{Error as VmMemoryError, GuestMemoryError, WriteVolatile}; use vmm_sys_util::errno; use crate::DirtyBitmap; -use crate::arch::arch_memory_regions; -use crate::utils::{get_page_size, mib_to_bytes, u64_to_usize}; +use crate::utils::{get_page_size, u64_to_usize}; use crate::vmm_config::machine_config::HugePageConfig; /// Type of GuestMemoryMmap. @@ -67,15 +66,15 @@ where /// Creates a GuestMemoryMmap with `size` in MiB backed by a memfd. fn memfd_backed( - mem_size_mib: usize, + regions: &[(GuestAddress, usize)], track_dirty_pages: bool, huge_pages: HugePageConfig, ) -> Result { - let memfd_file = create_memfd(mem_size_mib, huge_pages.into())?.into_file(); - let regions = arch_memory_regions(mib_to_bytes(mem_size_mib)).into_iter(); + let size = regions.iter().map(|&(_, size)| size as u64).sum(); + let memfd_file = create_memfd(size, huge_pages.into())?.into_file(); Self::create( - regions, + regions.iter().copied(), libc::MAP_SHARED | huge_pages.mmap_flags(), Some(memfd_file), track_dirty_pages, @@ -100,15 +99,10 @@ where /// and a `state` containing mapping information. fn snapshot_file( file: File, - state: &GuestMemoryState, + regions: impl Iterator, track_dirty_pages: bool, ) -> Result { - Self::create( - state.regions(), - libc::MAP_PRIVATE, - Some(file), - track_dirty_pages, - ) + Self::create(regions, libc::MAP_PRIVATE, Some(file), track_dirty_pages) } /// Describes GuestMemoryMmap through a GuestMemoryState struct. @@ -327,10 +321,9 @@ impl GuestMemoryExtension for GuestMemoryMmap { } fn create_memfd( - size: usize, + mem_size: u64, hugetlb_size: Option, ) -> Result { - let mem_size = mib_to_bytes(size); // Create a memfd. let opts = memfd::MemfdOptions::default() .hugetlb(hugetlb_size) @@ -340,7 +333,7 @@ fn create_memfd( // Resize to guest mem size. mem_file .as_file() - .set_len(mem_size as u64) + .set_len(mem_size) .map_err(MemoryError::MemfdSetLen)?; // Add seals to prevent further resizing. @@ -368,7 +361,7 @@ mod tests { use super::*; use crate::snapshot::Snapshot; - use crate::utils::get_page_size; + use crate::utils::{get_page_size, mib_to_bytes}; #[test] fn test_anonymous() { @@ -570,7 +563,7 @@ mod tests { guest_memory.dump(&mut memory_file).unwrap(); let restored_guest_memory = - GuestMemoryMmap::snapshot_file(memory_file, &memory_state, false).unwrap(); + GuestMemoryMmap::snapshot_file(memory_file, memory_state.regions(), false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; page_size * 2]; @@ -629,7 +622,7 @@ mod tests { // We can restore from this because this is the first dirty dump. let restored_guest_memory = - GuestMemoryMmap::snapshot_file(file, &memory_state, false).unwrap(); + GuestMemoryMmap::snapshot_file(file, memory_state.regions(), false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; region_size]; @@ -712,12 +705,11 @@ mod tests { #[test] fn test_create_memfd() { - let size = 1; - let size_mb = mib_to_bytes(1) as u64; + let size_bytes = mib_to_bytes(1) as u64; - let memfd = create_memfd(size, None).unwrap(); + let memfd = create_memfd(size_bytes, None).unwrap(); - assert_eq!(memfd.as_file().metadata().unwrap().len(), size_mb); + assert_eq!(memfd.as_file().metadata().unwrap().len(), size_bytes); memfd.as_file().set_len(0x69).unwrap_err(); let mut seals = memfd::SealsHashSet::new(); From 6ee792a3cf3ea1494cf730ba724a80539293c64a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 13:38:49 +0000 Subject: [PATCH 449/464] refactor: introduce struct VmCommon This struct will hold all the fields that are common between the x86_64 and aarch64 definition of `struct ArchVm`. For now, this is only the `VmFd`, but this will grow. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/vm.rs | 13 +++++------ src/vmm/src/arch/x86_64/vm.rs | 42 ++++++++++++++++++---------------- src/vmm/src/vstate/vm.rs | 25 ++++++++++++++------ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/vmm/src/arch/aarch64/vm.rs b/src/vmm/src/arch/aarch64/vm.rs index d1b6f07663f..ced5053e781 100644 --- a/src/vmm/src/arch/aarch64/vm.rs +++ b/src/vmm/src/arch/aarch64/vm.rs @@ -1,18 +1,17 @@ // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use kvm_ioctls::VmFd; use serde::{Deserialize, Serialize}; use crate::Kvm; use crate::arch::aarch64::gic::GicState; -use crate::vstate::vm::VmError; +use crate::vstate::vm::{VmCommon, VmError}; /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] pub struct ArchVm { - /// KVM file descriptor of microVM - pub fd: VmFd, + /// Architecture independent parts of a vm. + pub common: VmCommon, // On aarch64 we need to keep around the fd obtained by creating the VGIC device. irqchip_handle: Option, } @@ -31,9 +30,9 @@ pub enum ArchVmError { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &Kvm) -> Result { - let fd = Self::create_vm(kvm)?; + let common = Self::create_common(kvm)?; Ok(ArchVm { - fd, + common, irqchip_handle: None, }) } @@ -55,7 +54,7 @@ impl ArchVm { /// Creates the GIC (Global Interrupt Controller). pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), ArchVmError> { self.irqchip_handle = Some( - crate::arch::aarch64::gic::create_gic(&self.fd, vcpu_count.into(), None) + crate::arch::aarch64::gic::create_gic(self.fd(), vcpu_count.into(), None) .map_err(ArchVmError::VmCreateGIC)?, ); Ok(()) diff --git a/src/vmm/src/arch/x86_64/vm.rs b/src/vmm/src/arch/x86_64/vm.rs index ebce8ef02d0..cfed3bb479b 100644 --- a/src/vmm/src/arch/x86_64/vm.rs +++ b/src/vmm/src/arch/x86_64/vm.rs @@ -7,12 +7,12 @@ use kvm_bindings::{ KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY, MsrList, kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, }; -use kvm_ioctls::{Cap, VmFd}; +use kvm_ioctls::Cap; use serde::{Deserialize, Serialize}; use crate::arch::x86_64::msr::MsrError; use crate::utils::u64_to_usize; -use crate::vstate::vm::VmError; +use crate::vstate::vm::{VmCommon, VmError}; /// Error type for [`Vm::restore_state`] #[allow(missing_docs)] @@ -48,8 +48,8 @@ pub enum ArchVmError { /// Structure representing the current architecture's understand of what a "virtual machine" is. #[derive(Debug)] pub struct ArchVm { - /// KVM file descriptor of microVM - pub fd: VmFd, + /// Architecture independent parts of a vm + pub common: VmCommon, msrs_to_save: MsrList, /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct. /// @@ -60,7 +60,7 @@ pub struct ArchVm { impl ArchVm { /// Create a new `Vm` struct. pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result { - let fd = Self::create_vm(kvm)?; + let common = Self::create_common(kvm)?; let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?; @@ -70,7 +70,7 @@ impl ArchVm { // https://github.com/torvalds/linux/commit/be50b2065dfa3d88428fdfdc340d154d96bf6848 // // Cache the value in order not to call it at each vCPU creation. - let xsave2_size = match fd.check_extension_int(Cap::Xsave2) { + let xsave2_size = match common.fd.check_extension_int(Cap::Xsave2) { // Catch all negative values just in case although the possible negative return value // of ioctl() is only -1. ..=-1 => { @@ -84,11 +84,13 @@ impl ArchVm { ret => Some(usize::try_from(ret).unwrap()), }; - fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) + common + .fd + .set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS)) .map_err(ArchVmError::SetTssAddress)?; Ok(ArchVm { - fd, + common, msrs_to_save, xsave2_size, }) @@ -116,19 +118,19 @@ impl ArchVm { /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. /// - [`kvm_ioctls::VmFd::set_irqchip`] errors. pub fn restore_state(&mut self, state: &VmState) -> Result<(), ArchVmError> { - self.fd + self.fd() .set_pit2(&state.pitstate) .map_err(ArchVmError::SetPit2)?; - self.fd + self.fd() .set_clock(&state.clock) .map_err(ArchVmError::SetClock)?; - self.fd + self.fd() .set_irqchip(&state.pic_master) .map_err(ArchVmError::SetIrqChipPicMaster)?; - self.fd + self.fd() .set_irqchip(&state.pic_slave) .map_err(ArchVmError::SetIrqChipPicSlave)?; - self.fd + self.fd() .set_irqchip(&state.ioapic) .map_err(ArchVmError::SetIrqChipIoAPIC)?; Ok(()) @@ -136,7 +138,7 @@ impl ArchVm { /// Creates the irq chip and an in-kernel device model for the PIT. pub fn setup_irqchip(&self) -> Result<(), ArchVmError> { - self.fd + self.fd() .create_irq_chip() .map_err(ArchVmError::VmSetIrqChip)?; // We need to enable the emulation of a dummy speaker port stub so that writing to port 0x61 @@ -145,16 +147,16 @@ impl ArchVm { flags: KVM_PIT_SPEAKER_DUMMY, ..Default::default() }; - self.fd + self.fd() .create_pit2(pit_config) .map_err(ArchVmError::VmSetIrqChip) } /// Saves and returns the Kvm Vm state. pub fn save_state(&self) -> Result { - let pitstate = self.fd.get_pit2().map_err(ArchVmError::VmGetPit2)?; + let pitstate = self.fd().get_pit2().map_err(ArchVmError::VmGetPit2)?; - let mut clock = self.fd.get_clock().map_err(ArchVmError::VmGetClock)?; + let mut clock = self.fd().get_clock().map_err(ArchVmError::VmGetClock)?; // This bit is not accepted in SET_CLOCK, clear it. clock.flags &= !KVM_CLOCK_TSC_STABLE; @@ -162,7 +164,7 @@ impl ArchVm { chip_id: KVM_IRQCHIP_PIC_MASTER, ..Default::default() }; - self.fd + self.fd() .get_irqchip(&mut pic_master) .map_err(ArchVmError::VmGetIrqChip)?; @@ -170,7 +172,7 @@ impl ArchVm { chip_id: KVM_IRQCHIP_PIC_SLAVE, ..Default::default() }; - self.fd + self.fd() .get_irqchip(&mut pic_slave) .map_err(ArchVmError::VmGetIrqChip)?; @@ -178,7 +180,7 @@ impl ArchVm { chip_id: KVM_IRQCHIP_IOAPIC, ..Default::default() }; - self.fd + self.fd() .get_irqchip(&mut ioapic) .map_err(ArchVmError::VmGetIrqChip)?; diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index bb13b17ee99..e6bfc7726b4 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -15,6 +15,13 @@ use crate::logger::info; use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; use crate::vstate::vcpu::VcpuError; +/// Architecture independent parts of a VM. +#[derive(Debug)] +pub struct VmCommon { + /// The KVM file descriptor used to access this Vm. + pub fd: VmFd, +} + /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work #[rustfmt::skip] @@ -35,7 +42,7 @@ pub enum VmError { /// Contains Vm functions that are usable across CPU architectures impl Vm { /// Create a KVM VM - pub fn create_vm(kvm: &crate::vstate::kvm::Kvm) -> Result { + pub fn create_common(kvm: &crate::vstate::kvm::Kvm) -> Result { // It is known that KVM_CREATE_VM occasionally fails with EINTR on heavily loaded machines // with many VMs. // @@ -57,9 +64,10 @@ impl Vm { // retry, they have to start Firecracker from scratch. Doing retries in Firecracker makes // recovery faster and improves reliability. const MAX_ATTEMPTS: u32 = 5; - for attempt in 1..=MAX_ATTEMPTS { + let mut attempt = 1; + let fd = loop { match kvm.fd.create_vm() { - Ok(fd) => return Ok(fd), + Ok(fd) => break fd, Err(e) if e.errno() == libc::EINTR && attempt < MAX_ATTEMPTS => { info!("Attempt #{attempt} of KVM_CREATE_VM returned EINTR"); // Exponential backoff (1us, 2us, 4us, and 8us => 15us in total) @@ -67,8 +75,11 @@ impl Vm { } Err(e) => return Err(VmError::CreateVm(e)), } - } - unreachable!(); + + attempt += 1; + }; + + Ok(VmCommon { fd }) } /// Creates the specified number of [`Vcpu`]s. @@ -119,7 +130,7 @@ impl Vm { }; // SAFETY: Safe because the fd is a valid KVM file descriptor. - unsafe { self.fd.set_user_memory_region(memory_region) } + unsafe { self.fd().set_user_memory_region(memory_region) } }) .map_err(VmError::SetUserMemoryRegion)?; Ok(()) @@ -127,7 +138,7 @@ impl Vm { /// Gets a reference to the kvm file descriptor owned by this VM. pub fn fd(&self) -> &VmFd { - &self.fd + &self.common.fd } } From b6fed2805413ccc9039ebc0c89b8b8b42dee2cae Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 13:42:53 +0000 Subject: [PATCH 450/464] refactor: move check for not exceeding memslot limit into `struct Vm` This is to prepare for memory regions being registered to a VM incrementally. While we're at it, add a unit test for it. It completes in roughly 50s on my machine, and will become more useful later once we actually allow building mmap regions incrementally. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/kvm.rs | 4 -- src/vmm/src/arch/x86_64/kvm.rs | 4 -- src/vmm/src/builder.rs | 1 - src/vmm/src/vstate/kvm.rs | 21 +++------ src/vmm/src/vstate/vm.rs | 77 ++++++++++++++++++++++++++++++++- 5 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/vmm/src/arch/aarch64/kvm.rs b/src/vmm/src/arch/aarch64/kvm.rs index 12720f5066f..ed66d722970 100644 --- a/src/vmm/src/arch/aarch64/kvm.rs +++ b/src/vmm/src/arch/aarch64/kvm.rs @@ -22,8 +22,6 @@ pub struct OptionalCapabilities { pub struct Kvm { /// KVM fd. pub fd: KvmFd, - /// Maximum number of memory slots allowed by KVM. - pub max_memslots: usize, /// Additional capabilities that were specified in cpu template. pub kvm_cap_modifiers: Vec, } @@ -42,12 +40,10 @@ impl Kvm { /// Initialize [`Kvm`] type for Aarch64 architecture pub fn init_arch( fd: KvmFd, - max_memslots: usize, kvm_cap_modifiers: Vec, ) -> Result { Ok(Self { fd, - max_memslots, kvm_cap_modifiers, }) } diff --git a/src/vmm/src/arch/x86_64/kvm.rs b/src/vmm/src/arch/x86_64/kvm.rs index 4d77b0fdbb6..bad7f134d58 100644 --- a/src/vmm/src/arch/x86_64/kvm.rs +++ b/src/vmm/src/arch/x86_64/kvm.rs @@ -21,8 +21,6 @@ pub enum KvmArchError { pub struct Kvm { /// KVM fd. pub fd: KvmFd, - /// Maximum number of memory slots allowed by KVM. - pub max_memslots: usize, /// Additional capabilities that were specified in cpu template. pub kvm_cap_modifiers: Vec, /// Supported CpuIds. @@ -50,7 +48,6 @@ impl Kvm { /// Initialize [`Kvm`] type for x86_64 architecture pub fn init_arch( fd: KvmFd, - max_memslots: usize, kvm_cap_modifiers: Vec, ) -> Result { request_dynamic_xstate_features().map_err(KvmArchError::XstateFeatures)?; @@ -61,7 +58,6 @@ impl Kvm { Ok(Kvm { fd, - max_memslots, kvm_cap_modifiers, supported_cpuid, }) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 9b5924426a6..c274837596c 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -143,7 +143,6 @@ fn create_vmm_and_vcpus( // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. let mut vm = Vm::new(&kvm)?; - kvm.check_memory(&guest_memory)?; vm.memory_init(&guest_memory)?; let resource_allocator = ResourceAllocator::new()?; diff --git a/src/vmm/src/vstate/kvm.rs b/src/vmm/src/vstate/kvm.rs index b89d0e1a0d8..c857aa83080 100644 --- a/src/vmm/src/vstate/kvm.rs +++ b/src/vmm/src/vstate/kvm.rs @@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize}; pub use crate::arch::{Kvm, KvmArchError}; use crate::cpu_config::templates::KvmCapability; -use crate::vstate::memory::{GuestMemory, GuestMemoryMmap}; /// Errors associated with the wrappers over KVM ioctls. /// Needs `rustfmt::skip` to make multiline comments work @@ -21,8 +20,6 @@ pub enum KvmError { /** Error creating KVM object: {0} Make sure the user launching the firecracker process is \ configured on the /dev/kvm file's ACL. */ Kvm(kvm_ioctls::Error), - /// The number of configured slots is bigger than the maximum reported by KVM - NotEnoughMemorySlots, /// Architecture specific error: {0} ArchError(#[from] KvmArchError) } @@ -43,18 +40,7 @@ impl Kvm { // Check that all desired capabilities are supported. Self::check_capabilities(&kvm_fd, &total_caps).map_err(KvmError::Capabilities)?; - let max_memslots = kvm_fd.get_nr_memslots(); - - Ok(Kvm::init_arch(kvm_fd, max_memslots, kvm_cap_modifiers)?) - } - - /// Check guest memory does not have more regions than kvm allows. - pub fn check_memory(&self, guest_mem: &GuestMemoryMmap) -> Result<(), KvmError> { - if guest_mem.num_regions() > self.max_memslots { - Err(KvmError::NotEnoughMemorySlots) - } else { - Ok(()) - } + Ok(Kvm::init_arch(kvm_fd, kvm_cap_modifiers)?) } fn combine_capabilities(kvm_cap_modifiers: &[KvmCapability]) -> Vec { @@ -92,6 +78,11 @@ impl Kvm { kvm_cap_modifiers: self.kvm_cap_modifiers.clone(), } } + + /// Returns the maximal number of memslots allowed in a [`Vm`] + pub fn max_nr_memslots(&self) -> usize { + self.fd.get_nr_memslots() + } } /// Structure holding an general specific VM state. diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index e6bfc7726b4..863b2927c6d 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -20,6 +20,7 @@ use crate::vstate::vcpu::VcpuError; pub struct VmCommon { /// The KVM file descriptor used to access this Vm. pub fd: VmFd, + max_memslots: usize, } /// Errors associated with the wrappers over KVM ioctls. @@ -37,6 +38,8 @@ pub enum VmError { EventFd(std::io::Error), /// Failed to create vcpu: {0} CreateVcpu(VcpuError), + /// The number of configured slots is bigger than the maximum reported by KVM + NotEnoughMemorySlots, } /// Contains Vm functions that are usable across CPU architectures @@ -79,7 +82,10 @@ impl Vm { attempt += 1; }; - Ok(VmCommon { fd }) + Ok(VmCommon { + fd, + max_memslots: kvm.max_nr_memslots(), + }) } /// Creates the specified number of [`Vcpu`]s. @@ -104,6 +110,10 @@ impl Vm { /// Initializes the guest memory. pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { + if guest_mem.num_regions() > self.common.max_memslots { + return Err(VmError::NotEnoughMemorySlots); + } + self.set_kvm_memory_regions(guest_mem) } @@ -144,11 +154,16 @@ impl Vm { #[cfg(test)] pub(crate) mod tests { + use std::sync::Arc; + + use vm_memory::GuestAddress; + use vm_memory::mmap::MmapRegionBuilder; + use super::*; use crate::test_utils::single_region_mem; use crate::utils::mib_to_bytes; use crate::vstate::kvm::Kvm; - use crate::vstate::memory::GuestMemoryMmap; + use crate::vstate::memory::{GuestMemoryMmap, GuestRegionMmap}; // Auxiliary function being used throughout the tests. pub(crate) fn setup_vm() -> (Kvm, Vm) { @@ -198,6 +213,64 @@ pub(crate) mod tests { ); } + #[test] + fn test_too_many_regions() { + let (kvm, vm) = setup_vm(); + let max_nr_regions = kvm.max_nr_memslots(); + + let mut gm = GuestMemoryMmap::default(); + // SAFETY: valid mmap parameters + let ptr = unsafe { + libc::mmap( + std::ptr::null_mut(), + 0x1000, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_ANONYMOUS | libc::MAP_PRIVATE, + -1, + 0, + ) + }; + + assert_ne!(ptr, libc::MAP_FAILED); + + for i in 0..max_nr_regions { + // SAFETY: we assert above that the ptr is valid, and the size matches what we passed to + // mmap + let region = unsafe { + MmapRegionBuilder::new(0x1000) + .with_raw_mmap_pointer(ptr.cast()) + .build() + .unwrap() + }; + + let region = GuestRegionMmap::new(region, GuestAddress(i as u64 * 0x1000)).unwrap(); + + gm = gm.insert_region(Arc::new(region)).unwrap(); + } + + vm.memory_init(&gm).unwrap(); + + let vm = Vm::new(&kvm).unwrap(); + + // SAFETY: we assert above that the ptr is valid, and the size matches what we passed to + // mmap + let region = unsafe { + MmapRegionBuilder::new(0x1000) + .with_raw_mmap_pointer(ptr.cast()) + .build() + .unwrap() + }; + + let region = + GuestRegionMmap::new(region, GuestAddress(max_nr_regions as u64 * 0x1000)).unwrap(); + + let err = vm + .memory_init(&gm.insert_region(Arc::new(region)).unwrap()) + .unwrap_err(); + + assert!(matches!(err, VmError::NotEnoughMemorySlots), "{:?}", err); + } + #[test] fn test_create_vcpus() { let vcpu_count = 2; From 5b128359c4c41be98a86ecbc088247a8ad43d57a Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 14:01:07 +0000 Subject: [PATCH 451/464] refactor: store GuestMemoryMmap inside `struct Vm` Semantically, this is where it belong - the memory is associated with the virtual machine, not the virtual machine manager. But independently of this, it is needed for borrowchk reasons: In the future, each Vm will have two guest memory regions associated with it. One for traditional guest memory, and another that is dedicated to I/O (swiotlb region). Storing these two GuestMemoryMmap in `struct Vm` allows for a function as follows: fn io_memory(&self) -> &GuestMemoryMmap { self.io_memory.as_ref().unwrap_or(&self.normal_memory) } Such a function cannot live in `struct Vmm`, as that would mean borrowing the guest memory implies borrowing the entire `Vmm` object (because rustc is not intelligent enough to project split borrows past function calls - e.g. it doesn't know the references returned by io_memory() really only borrows the io_memory and normal_memory fields, not everything else.). However, this means it cannot be used in callsites where such splitting of borrows is required (e.g. everywhere where both a guest memory reference _and_ another Vmm field are passed by reference to a function). The `Option`-ness of the the guest_memory field is transitory. Signed-off-by: Patrick Roy --- src/vmm/src/acpi/mod.rs | 16 +++++----- src/vmm/src/arch/aarch64/mod.rs | 10 ++++--- src/vmm/src/arch/aarch64/vcpu.rs | 43 +++++++++++++-------------- src/vmm/src/arch/x86_64/mod.rs | 12 ++++---- src/vmm/src/arch/x86_64/vcpu.rs | 36 +++++++++++----------- src/vmm/src/arch/x86_64/vm.rs | 10 +++---- src/vmm/src/builder.rs | 14 ++++----- src/vmm/src/device_manager/legacy.rs | 2 +- src/vmm/src/device_manager/mmio.rs | 18 +++++------ src/vmm/src/device_manager/persist.rs | 2 +- src/vmm/src/gdb/arch/aarch64.rs | 4 ++- src/vmm/src/gdb/target.rs | 6 ++-- src/vmm/src/lib.rs | 11 +++---- src/vmm/src/persist.rs | 13 ++++---- src/vmm/src/vstate/vcpu.rs | 36 +++++++++++----------- src/vmm/src/vstate/vm.rs | 41 ++++++++++++++++--------- 16 files changed, 146 insertions(+), 128 deletions(-) diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index 59bca9eadfd..630cf590af8 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -215,7 +215,7 @@ mod tests { // A mocke Vmm object with 128MBs of memory let mut vmm = default_vmm(); let mut writer = AcpiTableWriter { - mem: &vmm.guest_memory, + mem: vmm.vm.guest_memory(), resource_allocator: &mut vmm.resource_allocator, }; @@ -264,13 +264,15 @@ mod tests { #[test] fn test_write_acpi_table_small_memory() { let mut vmm = default_vmm(); - vmm.guest_memory = arch_mem( - (SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096) - .try_into() - .unwrap(), - ); + vmm.vm + .memory_init(arch_mem( + (SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096) + .try_into() + .unwrap(), + )) + .unwrap(); let mut writer = AcpiTableWriter { - mem: &vmm.guest_memory, + mem: vmm.vm.guest_memory(), resource_allocator: &mut vmm.resource_allocator, }; diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index e19f496f019..99c2acf2f54 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -89,7 +89,7 @@ pub fn configure_system_for_boot( // Configure vCPUs with normalizing and setting the generated CPU configuration. for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu.configure( - &vmm.guest_memory, + vmm.vm.guest_memory(), entry_point, &vcpu_config, &optional_capabilities, @@ -105,7 +105,7 @@ pub fn configure_system_for_boot( .expect("Cannot create cstring from cmdline string"); let fdt = fdt::create_fdt( - &vmm.guest_memory, + vmm.vm.guest_memory(), vcpu_mpidr, cmdline, vmm.mmio_device_manager.get_device_info(), @@ -114,8 +114,10 @@ pub fn configure_system_for_boot( initrd, )?; - let fdt_address = GuestAddress(get_fdt_addr(&vmm.guest_memory)); - vmm.guest_memory.write_slice(fdt.as_slice(), fdt_address)?; + let fdt_address = GuestAddress(get_fdt_addr(vmm.vm.guest_memory())); + vmm.vm + .guest_memory() + .write_slice(fdt.as_slice(), fdt_address)?; Ok(()) } diff --git a/src/vmm/src/arch/aarch64/vcpu.rs b/src/vmm/src/arch/aarch64/vcpu.rs index 82bbd499deb..6a418f59b5e 100644 --- a/src/vmm/src/arch/aarch64/vcpu.rs +++ b/src/vmm/src/arch/aarch64/vcpu.rs @@ -502,27 +502,26 @@ mod tests { use crate::test_utils::arch_mem; use crate::vcpu::VcpuConfig; use crate::vstate::kvm::Kvm; - use crate::vstate::memory::GuestMemoryMmap; use crate::vstate::vm::Vm; use crate::vstate::vm::tests::setup_vm_with_memory; - fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { - let (kvm, mut vm, mut vcpu, vm_mem) = setup_vcpu_no_init(mem_size); + fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu) { + let (kvm, mut vm, mut vcpu) = setup_vcpu_no_init(mem_size); vcpu.init(&[]).unwrap(); vm.setup_irqchip(1).unwrap(); - (kvm, vm, vcpu, vm_mem) + (kvm, vm, vcpu) } - fn setup_vcpu_no_init(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { - let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size); + fn setup_vcpu_no_init(mem_size: usize) -> (Kvm, Vm, KvmVcpu) { + let (kvm, vm) = setup_vm_with_memory(mem_size); let vcpu = KvmVcpu::new(0, &vm).unwrap(); - (kvm, vm, vcpu, vm_mem) + (kvm, vm, vcpu) } #[test] fn test_create_vcpu() { - let (_, vm, _) = setup_vm_with_memory(0x1000); + let (_, vm) = setup_vm_with_memory(0x1000); unsafe { libc::close(vm.fd().as_raw_fd()) }; @@ -538,7 +537,7 @@ mod tests { #[test] fn test_configure_vcpu() { - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, vm, mut vcpu) = setup_vcpu(0x10000); let optional_capabilities = kvm.optional_capabilities(); let vcpu_config = VcpuConfig { @@ -548,7 +547,7 @@ mod tests { }; vcpu.configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(crate::arch::get_kernel_start()), protocol: BootProtocol::LinuxBoot, @@ -561,7 +560,7 @@ mod tests { unsafe { libc::close(vcpu.fd.as_raw_fd()) }; let err = vcpu.configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(crate::arch::get_kernel_start()), protocol: BootProtocol::LinuxBoot, @@ -583,7 +582,7 @@ mod tests { #[test] fn test_init_vcpu() { - let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); @@ -602,7 +601,7 @@ mod tests { #[test] fn test_vcpu_save_restore_state() { - let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); @@ -646,7 +645,7 @@ mod tests { // // This should fail with ENOEXEC. // https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165 - let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); let vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); @@ -656,7 +655,7 @@ mod tests { #[test] fn test_dump_cpu_config_after_init() { // Test `dump_cpu_config()` after `KVM_VCPU_INIT`. - let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); let mut vcpu = KvmVcpu::new(0, &vm).unwrap(); vm.setup_irqchip(1).unwrap(); vcpu.init(&[]).unwrap(); @@ -666,7 +665,7 @@ mod tests { #[test] fn test_setup_non_boot_vcpu() { - let (_, vm, _) = setup_vm_with_memory(0x1000); + let (_, vm) = setup_vm_with_memory(0x1000); let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap(); vcpu1.init(&[]).unwrap(); let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap(); @@ -678,7 +677,7 @@ mod tests { // Test `get_regs()` with valid register IDs. // - X0: 0x6030 0000 0010 0000 // - X1: 0x6030 0000 0010 0002 - let (_, _, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu) = setup_vcpu(0x10000); let reg_list = Vec::::from([0x6030000000100000, 0x6030000000100002]); get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap(); } @@ -686,14 +685,14 @@ mod tests { #[test] fn test_get_invalid_regs() { // Test `get_regs()` with invalid register IDs. - let (_, _, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu) = setup_vcpu(0x10000); let reg_list = Vec::::from([0x6030000000100001, 0x6030000000100003]); get_registers(&vcpu.fd, ®_list, &mut Aarch64RegisterVec::default()).unwrap_err(); } #[test] fn test_setup_regs() { - let (kvm, _, vcpu, _) = setup_vcpu_no_init(0x10000); + let (kvm, _, vcpu) = setup_vcpu_no_init(0x10000); let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000); let optional_capabilities = kvm.optional_capabilities(); @@ -730,7 +729,7 @@ mod tests { #[test] fn test_read_mpidr() { - let (_, _, vcpu, _) = setup_vcpu_no_init(0x10000); + let (_, _, vcpu) = setup_vcpu_no_init(0x10000); // Must fail when vcpu is not initialized yet. let res = vcpu.get_mpidr(); @@ -745,7 +744,7 @@ mod tests { #[test] fn test_get_set_regs() { - let (_, _, vcpu, _) = setup_vcpu_no_init(0x10000); + let (_, _, vcpu) = setup_vcpu_no_init(0x10000); // Must fail when vcpu is not initialized yet. let mut regs = Aarch64RegisterVec::default(); @@ -763,7 +762,7 @@ mod tests { fn test_mpstate() { use std::os::unix::io::AsRawFd; - let (_, _, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu) = setup_vcpu(0x10000); let res = vcpu.get_mpstate(); vcpu.set_mpstate(res.unwrap()).unwrap(); diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index fdfce03b069..30c98a0cbd3 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -169,7 +169,7 @@ pub fn configure_system_for_boot( // Configure vCPUs with normalizing and setting the generated CPU configuration. for vcpu in vcpus.iter_mut() { vcpu.kvm_vcpu - .configure(&vmm.guest_memory, entry_point, &vcpu_config)?; + .configure(vmm.vm.guest_memory(), entry_point, &vcpu_config)?; } // Write the kernel command line to guest memory. This is x86_64 specific, since on @@ -180,7 +180,7 @@ pub fn configure_system_for_boot( .expect("Cannot create cstring from cmdline string"); load_cmdline( - &vmm.guest_memory, + vmm.vm.guest_memory(), GuestAddress(crate::arch::x86_64::layout::CMDLINE_START), &boot_cmdline, ) @@ -188,7 +188,7 @@ pub fn configure_system_for_boot( // Note that this puts the mptable at the last 1k of Linux's 640k base RAM mptable::setup_mptable( - &vmm.guest_memory, + vmm.vm.guest_memory(), &mut vmm.resource_allocator, vcpu_config.vcpu_count, ) @@ -196,11 +196,11 @@ pub fn configure_system_for_boot( match entry_point.protocol { BootProtocol::PvhBoot => { - configure_pvh(&vmm.guest_memory, GuestAddress(CMDLINE_START), initrd)?; + configure_pvh(vmm.vm.guest_memory(), GuestAddress(CMDLINE_START), initrd)?; } BootProtocol::LinuxBoot => { configure_64bit_boot( - &vmm.guest_memory, + vmm.vm.guest_memory(), GuestAddress(CMDLINE_START), cmdline_size, initrd, @@ -211,7 +211,7 @@ pub fn configure_system_for_boot( // Create ACPI tables and write them in guest memory // For the time being we only support ACPI in x86_64 create_acpi_tables( - &vmm.guest_memory, + vmm.vm.guest_memory(), &mut vmm.resource_allocator, &vmm.mmio_device_manager, &vmm.acpi_device_manager, diff --git a/src/vmm/src/arch/x86_64/vcpu.rs b/src/vmm/src/arch/x86_64/vcpu.rs index 3cf53cdefc1..6c07720b573 100644 --- a/src/vmm/src/arch/x86_64/vcpu.rs +++ b/src/vmm/src/arch/x86_64/vcpu.rs @@ -825,11 +825,11 @@ mod tests { } } - fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) { - let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size); + fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu) { + let (kvm, vm) = setup_vm_with_memory(mem_size); vm.setup_irqchip().unwrap(); let vcpu = KvmVcpu::new(0, &vm).unwrap(); - (kvm, vm, vcpu, vm_mem) + (kvm, vm, vcpu) } fn is_at_least_cascade_lake() -> bool { @@ -864,12 +864,12 @@ mod tests { #[test] fn test_configure_vcpu() { - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, vm, mut vcpu) = setup_vcpu(0x10000); let vcpu_config = create_vcpu_config(&kvm, &vcpu, &CustomCpuTemplate::default()).unwrap(); assert_eq!( vcpu.configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(0), protocol: BootProtocol::LinuxBoot, @@ -886,7 +886,7 @@ mod tests { Ok(template) => match create_vcpu_config(kvm, vcpu, &template) { Ok(config) => vcpu .configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(crate::arch::get_kernel_start()), protocol: BootProtocol::LinuxBoot, @@ -946,7 +946,7 @@ mod tests { #[test] fn test_vcpu_cpuid_restore() { - let (kvm, _, vcpu, _mem) = setup_vcpu(0x10000); + let (kvm, _, vcpu) = setup_vcpu(0x10000); vcpu.fd.set_cpuid2(&kvm.supported_cpuid).unwrap(); // Mutate the CPUID. @@ -964,7 +964,7 @@ mod tests { drop(vcpu); // Restore the state into a new vcpu. - let (_, _vm, vcpu, _mem) = setup_vcpu(0x10000); + let (_, _vm, vcpu) = setup_vcpu(0x10000); let result2 = vcpu.restore_state(&state); assert!(result2.is_ok(), "{}", result2.unwrap_err()); @@ -984,7 +984,7 @@ mod tests { #[test] fn test_empty_cpuid_entries_removed() { // Test that `get_cpuid()` removes zeroed empty entries from the `KVM_GET_CPUID2` result. - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, vm, mut vcpu) = setup_vcpu(0x10000); let vcpu_config = VcpuConfig { vcpu_count: 1, smt: false, @@ -994,7 +994,7 @@ mod tests { }, }; vcpu.configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(0), protocol: BootProtocol::LinuxBoot, @@ -1042,7 +1042,7 @@ mod tests { // Since `KVM_SET_CPUID2` has not been called before vcpu configuration, all leaves should // be filled with zero. Therefore, `KvmVcpu::dump_cpu_config()` should fail with CPUID type // conversion error due to the lack of brand string info in leaf 0x0. - let (_, _, vcpu, _) = setup_vcpu(0x10000); + let (_, _, vcpu) = setup_vcpu(0x10000); match vcpu.dump_cpu_config() { Err(KvmVcpuError::ConvertCpuidType(_)) => (), Err(err) => panic!("Unexpected error: {err}"), @@ -1053,7 +1053,7 @@ mod tests { #[test] fn test_dump_cpu_config_with_configured_vcpu() { // Test `dump_cpu_config()` after vcpu configuration. - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000); + let (kvm, vm, mut vcpu) = setup_vcpu(0x10000); let vcpu_config = VcpuConfig { vcpu_count: 1, smt: false, @@ -1064,7 +1064,7 @@ mod tests { }; vcpu.configure( - &vm_mem, + vm.guest_memory(), EntryPoint { entry_addr: GuestAddress(0), protocol: BootProtocol::LinuxBoot, @@ -1080,7 +1080,7 @@ mod tests { fn test_is_tsc_scaling_required() { // Test `is_tsc_scaling_required` as if it were on the same // CPU model as the one in the snapshot state. - let (_, _, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu) = setup_vcpu(0x1000); { // The frequency difference is within tolerance. @@ -1122,7 +1122,7 @@ mod tests { #[test] fn test_set_tsc() { - let (kvm, _, vcpu, _) = setup_vcpu(0x1000); + let (kvm, _, vcpu) = setup_vcpu(0x1000); let mut state = vcpu.save_state().unwrap(); state.tsc_khz = Some( state.tsc_khz.unwrap() @@ -1147,7 +1147,7 @@ mod tests { fn test_get_msrs_with_msrs_to_save() { // Test `get_msrs()` with the MSR indices that should be serialized into snapshots. // The MSR indices should be valid and this test should succeed. - let (_, _, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu) = setup_vcpu(0x1000); vcpu.get_msrs(vcpu.msrs_to_save.iter().copied()).unwrap(); } @@ -1155,7 +1155,7 @@ mod tests { fn test_get_msrs_with_msrs_to_dump() { // Test `get_msrs()` with the MSR indices that should be dumped. // All the MSR indices should be valid and the call should succeed. - let (_, _, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu) = setup_vcpu(0x1000); let kvm = kvm_ioctls::Kvm::new().unwrap(); let msrs_to_dump = crate::arch::x86_64::msr::get_msrs_to_dump(&kvm).unwrap(); @@ -1168,7 +1168,7 @@ mod tests { // Test `get_msrs()` with unsupported MSR indices. This should return `VcpuGetMsr` error // that happens when `KVM_GET_MSRS` fails to populate MSR values in the middle and exits. // Currently, MSR indices 2..=4 are not listed as supported MSRs. - let (_, _, vcpu, _) = setup_vcpu(0x1000); + let (_, _, vcpu) = setup_vcpu(0x1000); let msr_index_list: Vec = vec![2, 3, 4]; match vcpu.get_msrs(msr_index_list.iter().copied()) { Err(KvmVcpuError::VcpuGetMsr(_)) => (), diff --git a/src/vmm/src/arch/x86_64/vm.rs b/src/vmm/src/arch/x86_64/vm.rs index cfed3bb479b..772bd3804b0 100644 --- a/src/vmm/src/arch/x86_64/vm.rs +++ b/src/vmm/src/arch/x86_64/vm.rs @@ -246,7 +246,7 @@ mod tests { // Irqchips, clock and pitstate are not configured so trying to save state should fail. vm.save_state().unwrap_err(); - let (_, vm, _mem) = setup_vm_with_memory(0x1000); + let (_, vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let vm_state = vm.save_state().unwrap(); @@ -259,7 +259,7 @@ mod tests { assert_eq!(vm_state.pic_slave.chip_id, KVM_IRQCHIP_PIC_SLAVE); assert_eq!(vm_state.ioapic.chip_id, KVM_IRQCHIP_IOAPIC); - let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); vm.restore_state(&vm_state).unwrap(); @@ -270,11 +270,11 @@ mod tests { fn test_vm_save_restore_state_bad_irqchip() { use kvm_bindings::KVM_NR_IRQCHIPS; - let (_, vm, _mem) = setup_vm_with_memory(0x1000); + let (_, vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let mut vm_state = vm.save_state().unwrap(); - let (_, mut vm, _mem) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); // Try to restore an invalid PIC Master chip ID @@ -299,7 +299,7 @@ mod tests { fn test_vmstate_serde() { let mut snapshot_data = vec![0u8; 10000]; - let (_, mut vm, _) = setup_vm_with_memory(0x1000); + let (_, mut vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let state = vm.save_state().unwrap(); Snapshot::serialize(&mut snapshot_data.as_mut_slice(), &state).unwrap(); diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index c274837596c..483843ebd77 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -143,7 +143,7 @@ fn create_vmm_and_vcpus( // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. let mut vm = Vm::new(&kvm)?; - vm.memory_init(&guest_memory)?; + vm.memory_init(guest_memory)?; let resource_allocator = ResourceAllocator::new()?; @@ -179,7 +179,6 @@ fn create_vmm_and_vcpus( shutdown_exit_code: None, kvm, vm, - guest_memory, uffd, vcpus_handles: Vec::new(), vcpus_exit_evt, @@ -468,7 +467,7 @@ pub fn build_microvm_from_snapshot( // Restore devices states. let mmio_ctor_args = MMIODevManagerConstructorArgs { - mem: &vmm.guest_memory, + mem: vmm.vm.guest_memory(), vm: vmm.vm.fd(), event_manager, resource_allocator: &mut vmm.resource_allocator, @@ -484,7 +483,7 @@ pub fn build_microvm_from_snapshot( { let acpi_ctor_args = ACPIDeviceManagerConstructorArgs { - mem: &vmm.guest_memory, + mem: vmm.vm.guest_memory(), resource_allocator: &mut vmm.resource_allocator, vm: vmm.vm.fd(), }; @@ -593,7 +592,7 @@ fn attach_virtio_device( event_manager.add_subscriber(device.clone()); // The device mutex mustn't be locked here otherwise it will deadlock. - let device = MmioTransport::new(vmm.guest_memory.clone(), device, is_vhost_user); + let device = MmioTransport::new(vmm.vm.guest_memory().clone(), device, is_vhost_user); vmm.mmio_device_manager .register_mmio_virtio_for_boot( vmm.vm.fd(), @@ -618,7 +617,7 @@ pub(crate) fn attach_boot_timer_device( } fn attach_vmgenid_device(vmm: &mut Vmm) -> Result<(), StartMicrovmError> { - let vmgenid = VmGenId::new(&vmm.guest_memory, &mut vmm.resource_allocator) + let vmgenid = VmGenId::new(vmm.vm.guest_memory(), &mut vmm.resource_allocator) .map_err(StartMicrovmError::CreateVMGenID)?; vmm.acpi_device_manager @@ -813,7 +812,7 @@ pub(crate) mod tests { } pub(crate) fn default_vmm() -> Vmm { - let (kvm, mut vm, guest_memory) = setup_vm_with_memory(mib_to_bytes(128)); + let (kvm, mut vm) = setup_vm_with_memory(mib_to_bytes(128)); let mmio_device_manager = MMIODeviceManager::new(); let acpi_device_manager = ACPIDeviceManager::new(); @@ -841,7 +840,6 @@ pub(crate) mod tests { shutdown_exit_code: None, kvm, vm, - guest_memory, uffd: None, vcpus_handles: Vec::new(), vcpus_exit_evt, diff --git a/src/vmm/src/device_manager/legacy.rs b/src/vmm/src/device_manager/legacy.rs index 7ced10dbbe5..20b008769a5 100644 --- a/src/vmm/src/device_manager/legacy.rs +++ b/src/vmm/src/device_manager/legacy.rs @@ -248,7 +248,7 @@ mod tests { #[test] fn test_register_legacy_devices() { - let (_, vm, _) = setup_vm_with_memory(0x1000); + let (_, vm) = setup_vm_with_memory(0x1000); vm.setup_irqchip().unwrap(); let mut ldm = PortIODeviceManager::new( Arc::new(Mutex::new(BusDevice::Serial(SerialDevice { diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index 20d9b381e1c..146d581afab 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -652,7 +652,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem).unwrap(); + vm.memory_init(guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -666,7 +666,7 @@ mod tests { device_manager .register_virtio_test_device( vm.fd(), - guest_mem, + vm.guest_memory().clone(), &mut resource_allocator, dummy, &mut cmdline, @@ -683,7 +683,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem).unwrap(); + vm.memory_init(guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -697,7 +697,7 @@ mod tests { device_manager .register_virtio_test_device( vm.fd(), - guest_mem.clone(), + vm.guest_memory().clone(), &mut resource_allocator, Arc::new(Mutex::new(DummyDevice::new())), &mut cmdline, @@ -711,7 +711,7 @@ mod tests { device_manager .register_virtio_test_device( vm.fd(), - guest_mem, + vm.guest_memory().clone(), &mut resource_allocator, Arc::new(Mutex::new(DummyDevice::new())), &mut cmdline, @@ -739,9 +739,7 @@ mod tests { let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(&guest_mem).unwrap(); - - let mem_clone = guest_mem.clone(); + vm.memory_init(guest_mem).unwrap(); #[cfg(target_arch = "x86_64")] vm.setup_irqchip().unwrap(); @@ -758,7 +756,7 @@ mod tests { let addr = device_manager .register_virtio_test_device( vm.fd(), - guest_mem, + vm.guest_memory().clone(), &mut resource_allocator, dummy, &mut cmdline, @@ -794,7 +792,7 @@ mod tests { device_manager .register_virtio_test_device( vm.fd(), - mem_clone, + vm.guest_memory().clone(), &mut resource_allocator, dummy2, &mut cmdline, diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index 0b8ad8eb04d..30a6387bc82 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -805,7 +805,7 @@ mod tests { let device_states: DeviceStates = Snapshot::deserialize(&mut buf.as_slice()).unwrap(); let vm_resources = &mut VmResources::default(); let restore_args = MMIODevManagerConstructorArgs { - mem: &vmm.guest_memory, + mem: vmm.vm.guest_memory(), vm: vmm.vm.fd(), event_manager: &mut event_manager, resource_allocator: &mut resource_allocator, diff --git a/src/vmm/src/gdb/arch/aarch64.rs b/src/vmm/src/gdb/arch/aarch64.rs index 9504a48fcc5..a462d677ff3 100644 --- a/src/vmm/src/gdb/arch/aarch64.rs +++ b/src/vmm/src/gdb/arch/aarch64.rs @@ -63,7 +63,9 @@ const PTE_ADDRESS_MASK: u64 = !0b111u64; /// Read a u64 value from a guest memory address fn read_address(vmm: &Vmm, address: u64) -> Result { let mut buf = [0; 8]; - vmm.guest_memory.read(&mut buf, GuestAddress(address))?; + vmm.vm + .guest_memory() + .read(&mut buf, GuestAddress(address))?; Ok(u64::from_le_bytes(buf)) } diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs index 3ff96d0c8b5..666861a0adb 100644 --- a/src/vmm/src/gdb/target.rs +++ b/src/vmm/src/gdb/target.rs @@ -399,7 +399,8 @@ impl MultiThreadBase for FirecrackerTarget { GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); - vmm.guest_memory + vmm.vm + .guest_memory() .read(&mut data[..read_len], GuestAddress(gpa as u64)) .map_err(|e| { error!("Error reading memory {e:?} gpa is {gpa}"); @@ -433,7 +434,8 @@ impl MultiThreadBase for FirecrackerTarget { GUEST_PAGE_SIZE - (u64_to_usize(gpa) & (GUEST_PAGE_SIZE - 1)), ); - vmm.guest_memory + vmm.vm + .guest_memory() .write(&data[..write_len], GuestAddress(gpa)) .map_err(|e| { error!("Error {e:?} writing memory at {gpa:#X}"); diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 5f173d3ae9c..e5c1cb97c66 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -310,7 +310,6 @@ pub struct Vmm { // Guest VM core resources. kvm: Kvm, vm: Vm, - guest_memory: GuestMemoryMmap, // Save UFFD in order to keep it open in the Firecracker process, as well. uffd: Option, vcpus_handles: Vec, @@ -521,7 +520,7 @@ impl Vmm { }; let device_states = self.mmio_device_manager.save(); - let memory_state = self.guest_memory.describe(); + let memory_state = self.vm.guest_memory().describe(); let acpi_dev_state = self.acpi_device_manager.save(); Ok(MicrovmState { @@ -593,7 +592,8 @@ impl Vmm { /// Retrieves the KVM dirty bitmap for each of the guest's memory regions. pub fn reset_dirty_bitmap(&self) { - self.guest_memory + self.vm + .guest_memory() .iter() .enumerate() .for_each(|(slot, region)| { @@ -607,7 +607,8 @@ impl Vmm { /// Retrieves the KVM dirty bitmap for each of the guest's memory regions. pub fn get_dirty_bitmap(&self) -> Result { let mut bitmap: DirtyBitmap = HashMap::new(); - self.guest_memory + self.vm + .guest_memory() .iter() .enumerate() .try_for_each(|(slot, region)| { @@ -736,7 +737,7 @@ impl Vmm { pub fn update_balloon_config(&mut self, amount_mib: u32) -> Result<(), BalloonError> { // The balloon cannot have a target size greater than the size of // the guest memory. - if u64::from(amount_mib) > mem_size_mib(&self.guest_memory) { + if u64::from(amount_mib) > mem_size_mib(self.vm.guest_memory()) { return Err(BalloonError::TooManyPagesRequested); } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 0f640cd38b9..3a39024a595 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -220,7 +220,7 @@ fn snapshot_memory_to_file( .map_err(|err| MemoryBackingFile("open", err))?; // Determine what size our total memory area is. - let mem_size_mib = mem_size_mib(&vmm.guest_memory); + let mem_size_mib = mem_size_mib(vmm.vm.guest_memory()); let expected_size = mem_size_mib * 1024 * 1024; if file_existed { @@ -249,15 +249,16 @@ fn snapshot_memory_to_file( match snapshot_type { SnapshotType::Diff => { let dirty_bitmap = vmm.get_dirty_bitmap().map_err(DirtyBitmap)?; - vmm.guest_memory + vmm.vm + .guest_memory() .dump_dirty(&mut file, &dirty_bitmap) .map_err(Memory) } SnapshotType::Full => { - let dump_res = vmm.guest_memory.dump(&mut file).map_err(Memory); + let dump_res = vmm.vm.guest_memory().dump(&mut file).map_err(Memory); if dump_res.is_ok() { vmm.reset_dirty_bitmap(); - vmm.guest_memory.reset_dirty(); + vmm.vm.guest_memory().reset_dirty(); } dump_res @@ -273,7 +274,7 @@ fn snapshot_memory_to_file( .for_each_virtio_device(|_, _, _, dev| { let d = dev.lock().unwrap(); if d.is_activated() { - d.mark_queue_memory_dirty(&vmm.guest_memory) + d.mark_queue_memory_dirty(vmm.vm.guest_memory()) } else { Ok(()) } @@ -754,7 +755,7 @@ mod tests { assert!(states.vsock_device.is_some()); assert!(states.balloon_device.is_some()); - let memory_state = vmm.guest_memory.describe(); + let memory_state = vmm.vm.guest_memory().describe(); let vcpu_states = vec![VcpuState::default()]; #[cfg(target_arch = "aarch64")] let mpidrs = construct_kvm_mpidrs(&vcpu_states); diff --git a/src/vmm/src/vstate/vcpu.rs b/src/vmm/src/vstate/vcpu.rs index 4e1bf8970a0..5d9afca3255 100644 --- a/src/vmm/src/vstate/vcpu.rs +++ b/src/vmm/src/vstate/vcpu.rs @@ -784,7 +784,7 @@ pub(crate) mod tests { #[test] fn test_handle_kvm_exit() { - let (_, _, mut vcpu, _vm_mem) = setup_vcpu(0x1000); + let (_, _, mut vcpu) = setup_vcpu(0x1000); let res = handle_kvm_exit(&mut vcpu.kvm_vcpu.peripherals, Ok(VcpuExit::Hlt)); assert_eq!(res.unwrap(), VcpuEmulation::Stopped); @@ -919,8 +919,8 @@ pub(crate) mod tests { // Auxiliary function being used throughout the tests. #[allow(unused_mut)] - pub(crate) fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, Vcpu, GuestMemoryMmap) { - let (kvm, mut vm, gm) = setup_vm_with_memory(mem_size); + pub(crate) fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, Vcpu) { + let (kvm, mut vm) = setup_vm_with_memory(mem_size); let (mut vcpus, _) = vm.create_vcpus(1).unwrap(); let mut vcpu = vcpus.remove(0); @@ -928,7 +928,7 @@ pub(crate) mod tests { #[cfg(target_arch = "aarch64")] vcpu.kvm_vcpu.init(&[]).unwrap(); - (kvm, vm, vcpu, gm) + (kvm, vm, vcpu) } fn load_good_kernel(vm_memory: &GuestMemoryMmap) -> GuestAddress { @@ -958,17 +958,17 @@ pub(crate) mod tests { entry_addr.kernel_load } - fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd, GuestMemoryMmap) { + fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd) { Vcpu::register_kick_signal_handler(); // Need enough mem to boot linux. let mem_size = mib_to_bytes(64); - let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(mem_size); + let (kvm, vm, mut vcpu) = setup_vcpu(mem_size); let vcpu_exit_evt = vcpu.exit_evt.try_clone().unwrap(); // Needs a kernel since we'll actually run this vcpu. let entry_point = EntryPoint { - entry_addr: load_good_kernel(&vm_mem), + entry_addr: load_good_kernel(vm.guest_memory()), protocol: BootProtocol::LinuxBoot, }; @@ -977,7 +977,7 @@ pub(crate) mod tests { use crate::cpu_config::x86_64::cpuid::Cpuid; vcpu.kvm_vcpu .configure( - &vm_mem, + vm.guest_memory(), entry_point, &VcpuConfig { vcpu_count: 1, @@ -994,7 +994,7 @@ pub(crate) mod tests { #[cfg(target_arch = "aarch64")] vcpu.kvm_vcpu .configure( - &vm_mem, + vm.guest_memory(), entry_point, &VcpuConfig { vcpu_count: 1, @@ -1013,12 +1013,12 @@ pub(crate) mod tests { // Wait for vCPUs to initialize their TLS before moving forward. barrier.wait(); - (vcpu_handle, vcpu_exit_evt, vm_mem) + (vcpu_handle, vcpu_exit_evt) } #[test] fn test_set_mmio_bus() { - let (_, _, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu) = setup_vcpu(0x1000); assert!(vcpu.kvm_vcpu.peripherals.mmio_bus.is_none()); vcpu.set_mmio_bus(crate::devices::Bus::new()); assert!(vcpu.kvm_vcpu.peripherals.mmio_bus.is_some()); @@ -1026,7 +1026,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_tls() { - let (_, _, mut vcpu, _mem) = setup_vcpu(0x1000); + let (_, _, mut vcpu) = setup_vcpu(0x1000); // Running on the TLS vcpu should fail before we actually initialize it. unsafe { @@ -1057,7 +1057,7 @@ pub(crate) mod tests { #[test] fn test_invalid_tls() { - let (_, _, mut vcpu, _) = setup_vcpu(0x1000); + let (_, _, mut vcpu) = setup_vcpu(0x1000); // Initialize vcpu TLS. vcpu.init_thread_local_data().unwrap(); // Trying to initialize non-empty TLS should error. @@ -1067,7 +1067,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_kick() { Vcpu::register_kick_signal_handler(); - let (_, vm, mut vcpu, _mem) = setup_vcpu(0x1000); + let (_, vm, mut vcpu) = setup_vcpu(0x1000); let mut kvm_run = kvm_ioctls::KvmRunWrapper::mmap_from_fd(&vcpu.kvm_vcpu.fd, vm.fd().run_size()) @@ -1122,7 +1122,7 @@ pub(crate) mod tests { #[test] fn test_immediate_exit_shortcircuits_execution() { - let (_, _, mut vcpu, _mem) = setup_vcpu(0x1000); + let (_, _, mut vcpu) = setup_vcpu(0x1000); vcpu.kvm_vcpu.fd.set_kvm_immediate_exit(1); // Set a dummy value to be returned by the emulate call @@ -1147,7 +1147,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_pause_resume() { - let (vcpu_handle, vcpu_exit_evt, _mem) = vcpu_configured_for_boot(); + let (vcpu_handle, vcpu_exit_evt) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1179,7 +1179,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_save_state_events() { - let (vcpu_handle, _vcpu_exit_evt, _mem) = vcpu_configured_for_boot(); + let (vcpu_handle, _vcpu_exit_evt) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1212,7 +1212,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_dump_cpu_config() { - let (vcpu_handle, _, _mem) = vcpu_configured_for_boot(); + let (vcpu_handle, _) = vcpu_configured_for_boot(); // Queue a DumpCpuConfig event, expect a DumpedCpuConfig response. vcpu_handle diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 863b2927c6d..568f3381459 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -21,6 +21,7 @@ pub struct VmCommon { /// The KVM file descriptor used to access this Vm. pub fd: VmFd, max_memslots: usize, + guest_memory: Option, } /// Errors associated with the wrappers over KVM ioctls. @@ -85,6 +86,7 @@ impl Vm { Ok(VmCommon { fd, max_memslots: kvm.max_nr_memslots(), + guest_memory: None, }) } @@ -109,12 +111,15 @@ impl Vm { } /// Initializes the guest memory. - pub fn memory_init(&self, guest_mem: &GuestMemoryMmap) -> Result<(), VmError> { + pub fn memory_init(&mut self, guest_mem: GuestMemoryMmap) -> Result<(), VmError> { if guest_mem.num_regions() > self.common.max_memslots { return Err(VmError::NotEnoughMemorySlots); } - self.set_kvm_memory_regions(guest_mem) + self.set_kvm_memory_regions(&guest_mem)?; + self.common.guest_memory = Some(guest_mem); + + Ok(()) } pub(crate) fn set_kvm_memory_regions( @@ -150,6 +155,14 @@ impl Vm { pub fn fd(&self) -> &VmFd { &self.common.fd } + + /// Gets a reference to this [`Vm`]'s [`GuestMemoryMmap`] object + pub fn guest_memory(&self) -> &GuestMemoryMmap { + self.common + .guest_memory + .as_ref() + .expect("attempt to access guest memory before calling Vm::memory_init()") + } } #[cfg(test)] @@ -163,7 +176,7 @@ pub(crate) mod tests { use crate::test_utils::single_region_mem; use crate::utils::mib_to_bytes; use crate::vstate::kvm::Kvm; - use crate::vstate::memory::{GuestMemoryMmap, GuestRegionMmap}; + use crate::vstate::memory::GuestRegionMmap; // Auxiliary function being used throughout the tests. pub(crate) fn setup_vm() -> (Kvm, Vm) { @@ -173,11 +186,11 @@ pub(crate) mod tests { } // Auxiliary function being used throughout the tests. - pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm, GuestMemoryMmap) { - let (kvm, vm) = setup_vm(); + pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm) { + let (kvm, mut vm) = setup_vm(); let gm = single_region_mem(mem_size); - vm.memory_init(&gm).unwrap(); - (kvm, vm, gm) + vm.memory_init(gm).unwrap(); + (kvm, vm) } #[test] @@ -189,10 +202,10 @@ pub(crate) mod tests { #[test] fn test_vm_memory_init() { - let (_, vm) = setup_vm(); + let (_, mut vm) = setup_vm(); // Create valid memory region and test that the initialization is successful. let gm = single_region_mem(0x1000); - vm.memory_init(&gm).unwrap(); + vm.memory_init(gm).unwrap(); } #[test] @@ -215,7 +228,7 @@ pub(crate) mod tests { #[test] fn test_too_many_regions() { - let (kvm, vm) = setup_vm(); + let (kvm, mut vm) = setup_vm(); let max_nr_regions = kvm.max_nr_memslots(); let mut gm = GuestMemoryMmap::default(); @@ -248,9 +261,9 @@ pub(crate) mod tests { gm = gm.insert_region(Arc::new(region)).unwrap(); } - vm.memory_init(&gm).unwrap(); + vm.memory_init(gm.clone()).unwrap(); - let vm = Vm::new(&kvm).unwrap(); + let mut vm = Vm::new(&kvm).unwrap(); // SAFETY: we assert above that the ptr is valid, and the size matches what we passed to // mmap @@ -265,7 +278,7 @@ pub(crate) mod tests { GuestRegionMmap::new(region, GuestAddress(max_nr_regions as u64 * 0x1000)).unwrap(); let err = vm - .memory_init(&gm.insert_region(Arc::new(region)).unwrap()) + .memory_init(gm.insert_region(Arc::new(region)).unwrap()) .unwrap_err(); assert!(matches!(err, VmError::NotEnoughMemorySlots), "{:?}", err); @@ -274,7 +287,7 @@ pub(crate) mod tests { #[test] fn test_create_vcpus() { let vcpu_count = 2; - let (_, mut vm, _) = setup_vm_with_memory(mib_to_bytes(128)); + let (_, mut vm) = setup_vm_with_memory(mib_to_bytes(128)); let (vcpu_vec, _) = vm.create_vcpus(vcpu_count).unwrap(); From 756b769eb405e783aaed896d571d95ba025ca0be Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 14:10:31 +0000 Subject: [PATCH 452/464] refactor: load kernel/initrd after create_vmm_and_vcpus() This is in preparation of guest memory itself only getting set up after the call to create_vmm_and_vcpus(). Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 483843ebd77..3adc2a10856 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -218,8 +218,6 @@ pub fn build_microvm_for_boot( .allocate_guest_memory() .map_err(StartMicrovmError::GuestMemory)?; - let entry_point = load_kernel(&boot_config.kernel_file, &guest_memory)?; - let initrd = InitrdConfig::from_config(boot_config, &guest_memory)?; // Clone the command-line so that a failed boot doesn't pollute the original. #[allow(unused_mut)] let mut boot_cmdline = boot_config.cmdline.clone(); @@ -238,6 +236,9 @@ pub fn build_microvm_for_boot( cpu_template.kvm_capabilities.clone(), )?; + let entry_point = load_kernel(&boot_config.kernel_file, vmm.vm.guest_memory())?; + let initrd = InitrdConfig::from_config(boot_config, vmm.vm.guest_memory())?; + #[cfg(feature = "gdb")] let (gdb_tx, gdb_rx) = mpsc::channel(); #[cfg(feature = "gdb")] From fddc29f3074dd8af81bb77d7ac732f2e5ba7e564 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 21 Mar 2025 14:52:16 +0000 Subject: [PATCH 453/464] refactor: build GuestMemoryMmap objects incrementally Add `Vm::register_memory_region[s]`, which allow adding new memory regions to a Vm incrementally (e.g. without overwriting the previously registered regions). To use this, have the functions in the `memory` module hand out Vec instead of GuestMemoryMmap, because vm_memory does not offer APIs for extracing the regions of a GuestMemoryMmap again. Signed-off-by: Patrick Roy --- src/vmm/benches/memory_access.rs | 3 +- src/vmm/src/acpi/mod.rs | 17 +- src/vmm/src/builder.rs | 17 +- src/vmm/src/device_manager/mmio.rs | 14 +- .../src/devices/virtio/block/virtio/io/mod.rs | 14 +- src/vmm/src/devices/virtio/vhost_user.rs | 16 +- src/vmm/src/persist.rs | 19 +- src/vmm/src/resources.rs | 9 +- src/vmm/src/test_utils/mod.rs | 25 +- src/vmm/src/vstate/memory.rs | 246 +++++++++--------- src/vmm/src/vstate/vm.rs | 168 ++++++------ 11 files changed, 289 insertions(+), 259 deletions(-) diff --git a/src/vmm/benches/memory_access.rs b/src/vmm/benches/memory_access.rs index 4dfb9dc9213..fe4f138db2d 100644 --- a/src/vmm/benches/memory_access.rs +++ b/src/vmm/benches/memory_access.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; -use vm_memory::GuestMemory; use vmm::resources::VmResources; use vmm::vmm_config::machine_config::{HugePageConfig, MachineConfig}; @@ -14,7 +13,7 @@ fn bench_single_page_fault(c: &mut Criterion, configuration: VmResources) { // Get a pointer to the first memory region (cannot do `.get_slice(GuestAddress(0), // 1)`, because on ARM64 guest memory does not start at physical // address 0). - let ptr = memory.iter().next().unwrap().as_ptr(); + let ptr = memory.first().unwrap().as_ptr(); // fine to return both here, because ptr is not a reference into `memory` (e.g. no // self-referential structs are happening here) diff --git a/src/vmm/src/acpi/mod.rs b/src/vmm/src/acpi/mod.rs index 630cf590af8..0b5c5edcbde 100644 --- a/src/vmm/src/acpi/mod.rs +++ b/src/vmm/src/acpi/mod.rs @@ -188,7 +188,9 @@ mod tests { use crate::acpi::{AcpiError, AcpiTableWriter}; use crate::arch::x86_64::layout::{SYSTEM_MEM_SIZE, SYSTEM_MEM_START}; use crate::builder::tests::default_vmm; - use crate::test_utils::arch_mem; + use crate::device_manager::resources::ResourceAllocator; + use crate::utils::u64_to_usize; + use crate::vstate::vm::tests::setup_vm_with_memory; struct MockSdt(Vec); @@ -263,17 +265,10 @@ mod tests { // change in the future. #[test] fn test_write_acpi_table_small_memory() { - let mut vmm = default_vmm(); - vmm.vm - .memory_init(arch_mem( - (SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096) - .try_into() - .unwrap(), - )) - .unwrap(); + let (_, vm) = setup_vm_with_memory(u64_to_usize(SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096)); let mut writer = AcpiTableWriter { - mem: vmm.vm.guest_memory(), - resource_allocator: &mut vmm.resource_allocator, + mem: vm.guest_memory(), + resource_allocator: &mut ResourceAllocator::new().unwrap(), }; let mut sdt = MockSdt(vec![0; usize::try_from(SYSTEM_MEM_SIZE).unwrap()]); diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 3adc2a10856..a835930020e 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -57,7 +57,7 @@ use crate::snapshot::Persist; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::MachineConfigError; use crate::vstate::kvm::Kvm; -use crate::vstate::memory::GuestMemoryMmap; +use crate::vstate::memory::GuestRegionMmap; use crate::vstate::vcpu::{Vcpu, VcpuError}; use crate::vstate::vm::Vm; use crate::{EventManager, Vmm, VmmError, device_manager}; @@ -134,7 +134,6 @@ impl std::convert::From for StartMicrovmError { fn create_vmm_and_vcpus( instance_info: &InstanceInfo, event_manager: &mut EventManager, - guest_memory: GuestMemoryMmap, uffd: Option, vcpu_count: u8, kvm_capabilities: Vec, @@ -143,7 +142,6 @@ fn create_vmm_and_vcpus( // Set up Kvm Vm and register memory regions. // Build custom CPU config if a custom template is provided. let mut vm = Vm::new(&kvm)?; - vm.memory_init(guest_memory)?; let resource_allocator = ResourceAllocator::new()?; @@ -230,12 +228,15 @@ pub fn build_microvm_for_boot( let (mut vmm, mut vcpus) = create_vmm_and_vcpus( instance_info, event_manager, - guest_memory, None, vm_resources.machine_config.vcpu_count, cpu_template.kvm_capabilities.clone(), )?; + vmm.vm + .register_memory_regions(guest_memory) + .map_err(VmmError::Vm)?; + let entry_point = load_kernel(&boot_config.kernel_file, vmm.vm.guest_memory())?; let initrd = InitrdConfig::from_config(boot_config, vmm.vm.guest_memory())?; @@ -413,7 +414,7 @@ pub fn build_microvm_from_snapshot( instance_info: &InstanceInfo, event_manager: &mut EventManager, microvm_state: MicrovmState, - guest_memory: GuestMemoryMmap, + guest_memory: Vec, uffd: Option, seccomp_filters: &BpfThreadMap, vm_resources: &mut VmResources, @@ -423,13 +424,17 @@ pub fn build_microvm_from_snapshot( let (mut vmm, mut vcpus) = create_vmm_and_vcpus( instance_info, event_manager, - guest_memory, uffd, vm_resources.machine_config.vcpu_count, microvm_state.kvm_state.kvm_cap_modifiers.clone(), ) .map_err(StartMicrovmError::Internal)?; + vmm.vm + .register_memory_regions(guest_memory) + .map_err(VmmError::Vm) + .map_err(StartMicrovmError::Internal)?; + #[cfg(target_arch = "x86_64")] { // Scale TSC to match, extract the TSC freq from the state if specified diff --git a/src/vmm/src/device_manager/mmio.rs b/src/vmm/src/device_manager/mmio.rs index 146d581afab..99bde6e2e78 100644 --- a/src/vmm/src/device_manager/mmio.rs +++ b/src/vmm/src/device_manager/mmio.rs @@ -532,7 +532,7 @@ mod tests { use crate::devices::virtio::ActivateError; use crate::devices::virtio::device::{IrqTrigger, VirtioDevice}; use crate::devices::virtio::queue::Queue; - use crate::test_utils::multi_region_mem; + use crate::test_utils::multi_region_mem_raw; use crate::vstate::kvm::Kvm; use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; @@ -649,10 +649,10 @@ mod tests { fn test_register_virtio_device() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); - let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); + let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(guest_mem).unwrap(); + vm.register_memory_regions(guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -680,10 +680,10 @@ mod tests { fn test_register_too_many_devices() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); - let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); + let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(guest_mem).unwrap(); + vm.register_memory_regions(guest_mem).unwrap(); let mut device_manager = MMIODeviceManager::new(); let mut resource_allocator = ResourceAllocator::new().unwrap(); @@ -736,10 +736,10 @@ mod tests { fn test_device_info() { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); - let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); + let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]); let kvm = Kvm::new(vec![]).expect("Cannot create Kvm"); let mut vm = Vm::new(&kvm).unwrap(); - vm.memory_init(guest_mem).unwrap(); + vm.register_memory_regions(guest_mem).unwrap(); #[cfg(target_arch = "x86_64")] vm.setup_irqchip().unwrap(); diff --git a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs index a43ab1e3b4b..79fe7c0c77d 100644 --- a/src/vmm/src/devices/virtio/block/virtio/io/mod.rs +++ b/src/vmm/src/devices/virtio/block/virtio/io/mod.rs @@ -194,7 +194,8 @@ pub mod tests { use crate::devices::virtio::block::virtio::device::FileEngineType; use crate::utils::u64_to_usize; use crate::vmm_config::machine_config::HugePageConfig; - use crate::vstate::memory::{Bitmap, Bytes, GuestMemory, GuestMemoryExtension}; + use crate::vstate::memory; + use crate::vstate::memory::{Bitmap, Bytes, GuestMemory}; const FILE_LEN: u32 = 1024; // 2 pages of memory should be enough to test read/write ops and also dirty tracking. @@ -230,10 +231,13 @@ pub mod tests { } fn create_mem() -> GuestMemoryMmap { - GuestMemoryMmap::anonymous( - [(GuestAddress(0), MEM_LEN)].into_iter(), - true, - HugePageConfig::None, + GuestMemoryMmap::from_regions( + memory::anonymous( + [(GuestAddress(0), MEM_LEN)].into_iter(), + true, + HugePageConfig::None, + ) + .unwrap(), ) .unwrap() } diff --git a/src/vmm/src/devices/virtio/vhost_user.rs b/src/vmm/src/devices/virtio/vhost_user.rs index aebd46be648..83174fbc4d3 100644 --- a/src/vmm/src/devices/virtio/vhost_user.rs +++ b/src/vmm/src/devices/virtio/vhost_user.rs @@ -468,14 +468,18 @@ pub(crate) mod tests { use super::*; use crate::test_utils::create_tmp_socket; - use crate::vstate::memory::{GuestAddress, GuestMemoryExtension}; + use crate::vstate::memory; + use crate::vstate::memory::GuestAddress; pub(crate) fn create_mem(file: File, regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap { - GuestMemoryMmap::create( - regions.iter().copied(), - libc::MAP_PRIVATE, - Some(file), - false, + GuestMemoryMmap::from_regions( + memory::create( + regions.iter().copied(), + libc::MAP_PRIVATE, + Some(file), + false, + ) + .unwrap(), ) .unwrap() } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 3a39024a595..ae58b329489 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -38,9 +38,8 @@ use crate::vmm_config::snapshot::{ CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType, }; use crate::vstate::kvm::KvmState; -use crate::vstate::memory::{ - GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryState, MemoryError, -}; +use crate::vstate::memory; +use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState, GuestRegionMmap, MemoryError}; use crate::vstate::vcpu::{VcpuSendEventError, VcpuState}; use crate::vstate::vm::VmState; use crate::{EventManager, Vmm, VmmError, mem_size_mib, vstate}; @@ -534,10 +533,9 @@ fn guest_memory_from_file( mem_file_path: &Path, mem_state: &GuestMemoryState, track_dirty_pages: bool, -) -> Result { +) -> Result, GuestMemoryFromFileError> { let mem_file = File::open(mem_file_path)?; - let guest_mem = - GuestMemoryMmap::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?; + let guest_mem = memory::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?; Ok(guest_mem) } @@ -562,7 +560,7 @@ fn guest_memory_from_uffd( track_dirty_pages: bool, enable_balloon: bool, huge_pages: HugePageConfig, -) -> Result<(GuestMemoryMmap, Option), GuestMemoryFromUffdError> { +) -> Result<(Vec, Option), GuestMemoryFromUffdError> { let (guest_memory, backend_mappings) = create_guest_memory(mem_state, track_dirty_pages, huge_pages)?; @@ -595,10 +593,9 @@ fn create_guest_memory( mem_state: &GuestMemoryState, track_dirty_pages: bool, huge_pages: HugePageConfig, -) -> Result<(GuestMemoryMmap, Vec), GuestMemoryFromUffdError> { - let guest_memory = - GuestMemoryMmap::anonymous(mem_state.regions(), track_dirty_pages, huge_pages)?; - let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions()); +) -> Result<(Vec, Vec), GuestMemoryFromUffdError> { + let guest_memory = memory::anonymous(mem_state.regions(), track_dirty_pages, huge_pages)?; + let mut backend_mappings = Vec::with_capacity(guest_memory.len()); let mut offset = 0; for mem_region in guest_memory.iter() { #[allow(deprecated)] diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 57d5c2f7444..98d71f4d0a6 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -29,7 +29,8 @@ use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; use crate::vmm_config::net::*; use crate::vmm_config::vsock::*; -use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap, MemoryError}; +use crate::vstate::memory; +use crate::vstate::memory::{GuestRegionMmap, MemoryError}; /// Errors encountered when configuring microVM resources. #[derive(Debug, thiserror::Error, displaydoc::Display)] @@ -440,7 +441,7 @@ impl VmResources { /// /// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise /// prefers anonymous memory for performance reasons. - pub fn allocate_guest_memory(&self) -> Result { + pub fn allocate_guest_memory(&self) -> Result, MemoryError> { let vhost_user_device_used = self .block .devices @@ -459,13 +460,13 @@ impl VmResources { let regions = crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib)); if vhost_user_device_used { - GuestMemoryMmap::memfd_backed( + memory::memfd_backed( regions.as_ref(), self.machine_config.track_dirty_pages, self.machine_config.huge_pages, ) } else { - GuestMemoryMmap::anonymous( + memory::anonymous( regions.into_iter(), self.machine_config.track_dirty_pages, self.machine_config.huge_pages, diff --git a/src/vmm/src/test_utils/mod.rs b/src/vmm/src/test_utils/mod.rs index 79026ba6de3..d3700c98925 100644 --- a/src/vmm/src/test_utils/mod.rs +++ b/src/vmm/src/test_utils/mod.rs @@ -15,7 +15,8 @@ use crate::test_utils::mock_resources::{MockBootSourceConfig, MockVmConfig, Mock use crate::vmm_config::boot_source::BootSourceConfig; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::HugePageConfig; -use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap}; +use crate::vstate::memory; +use crate::vstate::memory::{GuestMemoryMmap, GuestRegionMmap}; use crate::{EventManager, Vmm}; pub mod mock_resources; @@ -26,15 +27,31 @@ pub fn single_region_mem(region_size: usize) -> GuestMemoryMmap { single_region_mem_at(0, region_size) } +pub fn single_region_mem_raw(region_size: usize) -> Vec { + single_region_mem_at_raw(0, region_size) +} + /// Creates a [`GuestMemoryMmap`] with a single region of the given size starting at the given /// guest physical address `at` and without dirty tracking. pub fn single_region_mem_at(at: u64, size: usize) -> GuestMemoryMmap { multi_region_mem(&[(GuestAddress(at), size)]) } +pub fn single_region_mem_at_raw(at: u64, size: usize) -> Vec { + multi_region_mem_raw(&[(GuestAddress(at), size)]) +} + /// Creates a [`GuestMemoryMmap`] with multiple regions and without dirty page tracking. pub fn multi_region_mem(regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap { - GuestMemoryMmap::anonymous(regions.iter().copied(), false, HugePageConfig::None) + GuestMemoryMmap::from_regions( + memory::anonymous(regions.iter().copied(), false, HugePageConfig::None) + .expect("Cannot initialize memory"), + ) + .unwrap() +} + +pub fn multi_region_mem_raw(regions: &[(GuestAddress, usize)]) -> Vec { + memory::anonymous(regions.iter().copied(), false, HugePageConfig::None) .expect("Cannot initialize memory") } @@ -44,6 +61,10 @@ pub fn arch_mem(mem_size_bytes: usize) -> GuestMemoryMmap { multi_region_mem(&crate::arch::arch_memory_regions(mem_size_bytes)) } +pub fn arch_mem_raw(mem_size_bytes: usize) -> Vec { + multi_region_mem_raw(&crate::arch::arch_memory_regions(mem_size_bytes)) +} + pub fn create_vmm( _kernel_image: Option<&str>, is_diff: bool, diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index a5e1f9ba5e5..aaf51490738 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -9,7 +9,6 @@ use std::fs::File; use std::io::SeekFrom; use std::sync::Arc; -use libc::c_int; use serde::{Deserialize, Serialize}; pub use vm_memory::bitmap::{AtomicBitmap, BS, Bitmap, BitmapSlice}; pub use vm_memory::mmap::MmapRegionBuilder; @@ -51,60 +50,93 @@ pub enum MemoryError { OffsetTooLarge, } +/// Creates a `Vec` of `GuestRegionMmap` with the given configuration +pub fn create( + regions: impl Iterator, + mmap_flags: libc::c_int, + file: Option, + track_dirty_pages: bool, +) -> Result, MemoryError> { + let mut offset = 0; + let file = file.map(Arc::new); + regions + .map(|(start, size)| { + let mut builder = MmapRegionBuilder::new_with_bitmap( + size, + track_dirty_pages.then(|| AtomicBitmap::with_len(size)), + ) + .with_mmap_prot(libc::PROT_READ | libc::PROT_WRITE) + .with_mmap_flags(libc::MAP_NORESERVE | mmap_flags); + + if let Some(ref file) = file { + let file_offset = FileOffset::from_arc(Arc::clone(file), offset); + + builder = builder.with_file_offset(file_offset); + } + + offset = match offset.checked_add(size as u64) { + None => return Err(MemoryError::OffsetTooLarge), + Some(new_off) if new_off >= i64::MAX as u64 => { + return Err(MemoryError::OffsetTooLarge); + } + Some(new_off) => new_off, + }; + + GuestRegionMmap::new( + builder.build().map_err(MemoryError::MmapRegionError)?, + start, + ) + .map_err(MemoryError::VmMemoryError) + }) + .collect::, _>>() +} + +/// Creates a GuestMemoryMmap with `size` in MiB backed by a memfd. +pub fn memfd_backed( + regions: &[(GuestAddress, usize)], + track_dirty_pages: bool, + huge_pages: HugePageConfig, +) -> Result, MemoryError> { + let size = regions.iter().map(|&(_, size)| size as u64).sum(); + let memfd_file = create_memfd(size, huge_pages.into())?.into_file(); + + create( + regions.iter().copied(), + libc::MAP_SHARED | huge_pages.mmap_flags(), + Some(memfd_file), + track_dirty_pages, + ) +} + +/// Creates a GuestMemoryMmap from raw regions. +pub fn anonymous( + regions: impl Iterator, + track_dirty_pages: bool, + huge_pages: HugePageConfig, +) -> Result, MemoryError> { + create( + regions, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | huge_pages.mmap_flags(), + None, + track_dirty_pages, + ) +} + +/// Creates a GuestMemoryMmap given a `file` containing the data +/// and a `state` containing mapping information. +pub fn snapshot_file( + file: File, + regions: impl Iterator, + track_dirty_pages: bool, +) -> Result, MemoryError> { + create(regions, libc::MAP_PRIVATE, Some(file), track_dirty_pages) +} + /// Defines the interface for snapshotting memory. pub trait GuestMemoryExtension where Self: Sized, { - /// Creates a [`GuestMemoryMmap`] with the given configuration - fn create( - regions: impl Iterator, - mmap_flags: libc::c_int, - file: Option, - track_dirty_pages: bool, - ) -> Result; - - /// Creates a GuestMemoryMmap with `size` in MiB backed by a memfd. - fn memfd_backed( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result { - let size = regions.iter().map(|&(_, size)| size as u64).sum(); - let memfd_file = create_memfd(size, huge_pages.into())?.into_file(); - - Self::create( - regions.iter().copied(), - libc::MAP_SHARED | huge_pages.mmap_flags(), - Some(memfd_file), - track_dirty_pages, - ) - } - - /// Creates a GuestMemoryMmap from raw regions. - fn anonymous( - regions: impl Iterator, - track_dirty_pages: bool, - huge_pages: HugePageConfig, - ) -> Result { - Self::create( - regions, - libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | huge_pages.mmap_flags(), - None, - track_dirty_pages, - ) - } - - /// Creates a GuestMemoryMmap given a `file` containing the data - /// and a `state` containing mapping information. - fn snapshot_file( - file: File, - regions: impl Iterator, - track_dirty_pages: bool, - ) -> Result { - Self::create(regions, libc::MAP_PRIVATE, Some(file), track_dirty_pages) - } - /// Describes GuestMemoryMmap through a GuestMemoryState struct. fn describe(&self) -> GuestMemoryState; @@ -157,48 +189,6 @@ impl GuestMemoryState { } impl GuestMemoryExtension for GuestMemoryMmap { - fn create( - regions: impl Iterator, - mmap_flags: c_int, - file: Option, - track_dirty_pages: bool, - ) -> Result { - let mut offset = 0; - let file = file.map(Arc::new); - let regions = regions - .map(|(start, size)| { - let mut builder = MmapRegionBuilder::new_with_bitmap( - size, - track_dirty_pages.then(|| AtomicBitmap::with_len(size)), - ) - .with_mmap_prot(libc::PROT_READ | libc::PROT_WRITE) - .with_mmap_flags(libc::MAP_NORESERVE | mmap_flags); - - if let Some(ref file) = file { - let file_offset = FileOffset::from_arc(Arc::clone(file), offset); - - builder = builder.with_file_offset(file_offset); - } - - offset = match offset.checked_add(size as u64) { - None => return Err(MemoryError::OffsetTooLarge), - Some(new_off) if new_off >= i64::MAX as u64 => { - return Err(MemoryError::OffsetTooLarge); - } - Some(new_off) => new_off, - }; - - GuestRegionMmap::new( - builder.build().map_err(MemoryError::MmapRegionError)?, - start, - ) - .map_err(MemoryError::VmMemoryError) - }) - .collect::, _>>()?; - - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } - /// Describes GuestMemoryMmap through a GuestMemoryState struct. fn describe(&self) -> GuestMemoryState { let mut guest_memory_state = GuestMemoryState::default(); @@ -374,7 +364,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::anonymous( + let guest_memory = anonymous( regions.into_iter(), dirty_page_tracking, HugePageConfig::None, @@ -396,8 +386,10 @@ mod tests { (GuestAddress(region_size as u64), region_size), // pages 3-5 (GuestAddress(region_size as u64 * 2), region_size), // pages 6-8 ]; - let guest_memory = - GuestMemoryMmap::anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); let dirty_map = [ // page 0: not dirty @@ -452,10 +444,13 @@ mod tests { let region_size = page_size * 3; // Test with a single region - let guest_memory = GuestMemoryMmap::anonymous( - [(GuestAddress(0), region_size)].into_iter(), - false, - HugePageConfig::None, + let guest_memory = GuestMemoryMmap::from_regions( + anonymous( + [(GuestAddress(0), region_size)].into_iter(), + false, + HugePageConfig::None, + ) + .unwrap(), ) .unwrap(); check_serde(&guest_memory); @@ -466,8 +461,10 @@ mod tests { (GuestAddress(region_size as u64), region_size), // pages 3-5 (GuestAddress(region_size as u64 * 2), region_size), // pages 6-8 ]; - let guest_memory = - GuestMemoryMmap::anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); check_serde(&guest_memory); } @@ -480,9 +477,10 @@ mod tests { (GuestAddress(0), page_size), (GuestAddress(page_size as u64 * 2), page_size), ]; - let guest_memory = - GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) - .unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(mem_regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); let expected_memory_state = GuestMemoryState { regions: vec![ @@ -505,9 +503,10 @@ mod tests { (GuestAddress(0), page_size * 3), (GuestAddress(page_size as u64 * 4), page_size * 3), ]; - let guest_memory = - GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) - .unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(mem_regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); let expected_memory_state = GuestMemoryState { regions: vec![ @@ -538,9 +537,10 @@ mod tests { (region_1_address, region_size), (region_2_address, region_size), ]; - let guest_memory = - GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) - .unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(mem_regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -562,8 +562,10 @@ mod tests { let mut memory_file = TempFile::new().unwrap().into_file(); guest_memory.dump(&mut memory_file).unwrap(); - let restored_guest_memory = - GuestMemoryMmap::snapshot_file(memory_file, memory_state.regions(), false).unwrap(); + let restored_guest_memory = GuestMemoryMmap::from_regions( + snapshot_file(memory_file, memory_state.regions(), false).unwrap(), + ) + .unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; page_size * 2]; @@ -590,9 +592,10 @@ mod tests { (region_1_address, region_size), (region_2_address, region_size), ]; - let guest_memory = - GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) - .unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(mem_regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -621,8 +624,10 @@ mod tests { guest_memory.dump_dirty(&mut file, &dirty_bitmap).unwrap(); // We can restore from this because this is the first dirty dump. - let restored_guest_memory = - GuestMemoryMmap::snapshot_file(file, memory_state.regions(), false).unwrap(); + let restored_guest_memory = GuestMemoryMmap::from_regions( + snapshot_file(file, memory_state.regions(), false).unwrap(), + ) + .unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; region_size]; @@ -678,9 +683,10 @@ mod tests { (region_1_address, region_size), (region_2_address, region_size), ]; - let guest_memory = - GuestMemoryMmap::anonymous(mem_regions.into_iter(), true, HugePageConfig::None) - .unwrap(); + let guest_memory = GuestMemoryMmap::from_regions( + anonymous(mem_regions.into_iter(), true, HugePageConfig::None).unwrap(), + ) + .unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 568f3381459..6c1d094ff78 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -5,6 +5,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. +use std::sync::Arc; + use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; @@ -12,7 +14,9 @@ use vmm_sys_util::eventfd::EventFd; use crate::Vcpu; pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState}; use crate::logger::info; -use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; +use crate::vstate::memory::{ + Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap, +}; use crate::vstate::vcpu::VcpuError; /// Architecture independent parts of a VM. @@ -21,7 +25,7 @@ pub struct VmCommon { /// The KVM file descriptor used to access this Vm. pub fd: VmFd, max_memslots: usize, - guest_memory: Option, + guest_memory: GuestMemoryMmap, } /// Errors associated with the wrappers over KVM ioctls. @@ -41,6 +45,8 @@ pub enum VmError { CreateVcpu(VcpuError), /// The number of configured slots is bigger than the maximum reported by KVM NotEnoughMemorySlots, + /// Memory Error: {0} + VmMemory(#[from] vm_memory::Error), } /// Contains Vm functions that are usable across CPU architectures @@ -86,7 +92,7 @@ impl Vm { Ok(VmCommon { fd, max_memslots: kvm.max_nr_memslots(), - guest_memory: None, + guest_memory: GuestMemoryMmap::default(), }) } @@ -110,44 +116,54 @@ impl Vm { Ok((vcpus, exit_evt)) } - /// Initializes the guest memory. - pub fn memory_init(&mut self, guest_mem: GuestMemoryMmap) -> Result<(), VmError> { - if guest_mem.num_regions() > self.common.max_memslots { - return Err(VmError::NotEnoughMemorySlots); + /// Register a list of new memory regions to this [`Vm`]. + pub fn register_memory_regions( + &mut self, + regions: Vec, + ) -> Result<(), VmError> { + for region in regions { + self.register_memory_region(region)? } - self.set_kvm_memory_regions(&guest_mem)?; - self.common.guest_memory = Some(guest_mem); - Ok(()) } - pub(crate) fn set_kvm_memory_regions( - &self, - guest_mem: &GuestMemoryMmap, - ) -> Result<(), VmError> { - guest_mem - .iter() - .zip(0u32..) - .try_for_each(|(region, slot)| { - let flags = if region.bitmap().is_some() { - KVM_MEM_LOG_DIRTY_PAGES - } else { - 0 - }; - - let memory_region = kvm_userspace_memory_region { - slot, - guest_phys_addr: region.start_addr().raw_value(), - memory_size: region.len(), - userspace_addr: region.as_ptr() as u64, - flags, - }; - - // SAFETY: Safe because the fd is a valid KVM file descriptor. - unsafe { self.fd().set_user_memory_region(memory_region) } - }) - .map_err(VmError::SetUserMemoryRegion)?; + /// Register a new memory region to this [`Vm`]. + pub fn register_memory_region(&mut self, region: GuestRegionMmap) -> Result<(), VmError> { + let next_slot = self + .guest_memory() + .num_regions() + .try_into() + .map_err(|_| VmError::NotEnoughMemorySlots)?; + if next_slot as usize >= self.common.max_memslots { + return Err(VmError::NotEnoughMemorySlots); + } + + let flags = if region.bitmap().is_some() { + KVM_MEM_LOG_DIRTY_PAGES + } else { + 0 + }; + + let memory_region = kvm_userspace_memory_region { + slot: next_slot, + guest_phys_addr: region.start_addr().raw_value(), + memory_size: region.len(), + userspace_addr: region.as_ptr() as u64, + flags, + }; + + let new_guest_memory = self.common.guest_memory.insert_region(Arc::new(region))?; + + // SAFETY: Safe because the fd is a valid KVM file descriptor. + unsafe { + self.fd() + .set_user_memory_region(memory_region) + .map_err(VmError::SetUserMemoryRegion)?; + } + + self.common.guest_memory = new_guest_memory; + Ok(()) } @@ -158,22 +174,17 @@ impl Vm { /// Gets a reference to this [`Vm`]'s [`GuestMemoryMmap`] object pub fn guest_memory(&self) -> &GuestMemoryMmap { - self.common - .guest_memory - .as_ref() - .expect("attempt to access guest memory before calling Vm::memory_init()") + &self.common.guest_memory } } #[cfg(test)] pub(crate) mod tests { - use std::sync::Arc; - use vm_memory::GuestAddress; use vm_memory::mmap::MmapRegionBuilder; use super::*; - use crate::test_utils::single_region_mem; + use crate::test_utils::single_region_mem_raw; use crate::utils::mib_to_bytes; use crate::vstate::kvm::Kvm; use crate::vstate::memory::GuestRegionMmap; @@ -188,8 +199,8 @@ pub(crate) mod tests { // Auxiliary function being used throughout the tests. pub(crate) fn setup_vm_with_memory(mem_size: usize) -> (Kvm, Vm) { let (kvm, mut vm) = setup_vm(); - let gm = single_region_mem(mem_size); - vm.memory_init(gm).unwrap(); + let gm = single_region_mem_raw(mem_size); + vm.register_memory_regions(gm).unwrap(); (kvm, vm) } @@ -201,29 +212,21 @@ pub(crate) mod tests { } #[test] - fn test_vm_memory_init() { + fn test_register_memory_regions() { let (_, mut vm) = setup_vm(); - // Create valid memory region and test that the initialization is successful. - let gm = single_region_mem(0x1000); - vm.memory_init(gm).unwrap(); - } - - #[test] - fn test_set_kvm_memory_regions() { - let (_, vm) = setup_vm(); - - let gm = single_region_mem(0x1000); - let res = vm.set_kvm_memory_regions(&gm); - res.unwrap(); // Trying to set a memory region with a size that is not a multiple of GUEST_PAGE_SIZE // will result in error. - let gm = single_region_mem(0x10); - let res = vm.set_kvm_memory_regions(&gm); + let gm = single_region_mem_raw(0x10); + let res = vm.register_memory_regions(gm); assert_eq!( res.unwrap_err().to_string(), "Cannot set the memory regions: Invalid argument (os error 22)" ); + + let gm = single_region_mem_raw(0x1000); + let res = vm.register_memory_regions(gm); + res.unwrap(); } #[test] @@ -231,7 +234,6 @@ pub(crate) mod tests { let (kvm, mut vm) = setup_vm(); let max_nr_regions = kvm.max_nr_memslots(); - let mut gm = GuestMemoryMmap::default(); // SAFETY: valid mmap parameters let ptr = unsafe { libc::mmap( @@ -246,7 +248,7 @@ pub(crate) mod tests { assert_ne!(ptr, libc::MAP_FAILED); - for i in 0..max_nr_regions { + for i in 0..=max_nr_regions { // SAFETY: we assert above that the ptr is valid, and the size matches what we passed to // mmap let region = unsafe { @@ -258,30 +260,26 @@ pub(crate) mod tests { let region = GuestRegionMmap::new(region, GuestAddress(i as u64 * 0x1000)).unwrap(); - gm = gm.insert_region(Arc::new(region)).unwrap(); + let res = vm.register_memory_region(region); + + if i >= max_nr_regions { + assert!( + matches!(res, Err(VmError::NotEnoughMemorySlots)), + "{:?} at iteration {} - max_nr_memslots: {}", + res, + i, + max_nr_regions + ); + } else { + res.unwrap_or_else(|_| { + panic!( + "to be able to insert more regions in iteration {i} - max_nr_memslots: \ + {max_nr_regions} - num_regions: {}", + vm.guest_memory().num_regions() + ) + }); + } } - - vm.memory_init(gm.clone()).unwrap(); - - let mut vm = Vm::new(&kvm).unwrap(); - - // SAFETY: we assert above that the ptr is valid, and the size matches what we passed to - // mmap - let region = unsafe { - MmapRegionBuilder::new(0x1000) - .with_raw_mmap_pointer(ptr.cast()) - .build() - .unwrap() - }; - - let region = - GuestRegionMmap::new(region, GuestAddress(max_nr_regions as u64 * 0x1000)).unwrap(); - - let err = vm - .memory_init(gm.insert_region(Arc::new(region)).unwrap()) - .unwrap_err(); - - assert!(matches!(err, VmError::NotEnoughMemorySlots), "{:?}", err); } #[test] From 538357fd0bfa64789f5cb1fffaec711b3f1241a8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Mar 2025 13:31:30 +0000 Subject: [PATCH 454/464] refactor: move GuestMemoryState into VmState Since the guest memory is now stored in `struct Vm`, we can more easily store the guest memory state inside the VmState. Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/vm.rs | 5 +++++ src/vmm/src/arch/x86_64/vm.rs | 4 ++++ src/vmm/src/lib.rs | 6 +----- src/vmm/src/persist.rs | 8 ++------ src/vmm/src/vstate/vm.rs | 3 ++- src/vmm/tests/integration_tests.rs | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/vmm/src/arch/aarch64/vm.rs b/src/vmm/src/arch/aarch64/vm.rs index ced5053e781..e54723f5b6d 100644 --- a/src/vmm/src/arch/aarch64/vm.rs +++ b/src/vmm/src/arch/aarch64/vm.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::Kvm; use crate::arch::aarch64::gic::GicState; +use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState}; use crate::vstate::vm::{VmCommon, VmError}; /// Structure representing the current architecture's understand of what a "virtual machine" is. @@ -68,6 +69,7 @@ impl ArchVm { /// Saves and returns the Kvm Vm state. pub fn save_state(&self, mpidrs: &[u64]) -> Result { Ok(VmState { + memory: self.common.guest_memory.describe(), gic: self .get_irqchip() .save_device(mpidrs) @@ -84,6 +86,7 @@ impl ArchVm { self.get_irqchip() .restore_device(mpidrs, &state.gic) .map_err(ArchVmError::RestoreGic)?; + Ok(()) } } @@ -91,6 +94,8 @@ impl ArchVm { /// Structure holding an general specific VM state. #[derive(Debug, Default, Serialize, Deserialize)] pub struct VmState { + /// Guest memory state + pub memory: GuestMemoryState, /// GIC state. pub gic: GicState, } diff --git a/src/vmm/src/arch/x86_64/vm.rs b/src/vmm/src/arch/x86_64/vm.rs index 772bd3804b0..e84b4338e35 100644 --- a/src/vmm/src/arch/x86_64/vm.rs +++ b/src/vmm/src/arch/x86_64/vm.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::arch::x86_64::msr::MsrError; use crate::utils::u64_to_usize; +use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState}; use crate::vstate::vm::{VmCommon, VmError}; /// Error type for [`Vm::restore_state`] @@ -185,6 +186,7 @@ impl ArchVm { .map_err(ArchVmError::VmGetIrqChip)?; Ok(VmState { + memory: self.common.guest_memory.describe(), pitstate, clock, pic_master, @@ -207,6 +209,8 @@ impl ArchVm { #[derive(Default, Deserialize, Serialize)] /// Structure holding VM kvm state. pub struct VmState { + /// guest memory state + pub memory: GuestMemoryState, pitstate: kvm_pit_state2, clock: kvm_clock_data, // TODO: rename this field to adopt inclusive language once Linux updates it, too. diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index e5c1cb97c66..eaa3cf1816f 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -151,9 +151,7 @@ use crate::rate_limiter::BucketUpdate; use crate::snapshot::Persist; use crate::utils::u64_to_usize; use crate::vmm_config::instance_info::{InstanceInfo, VmState}; -use crate::vstate::memory::{ - GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryRegion, -}; +use crate::vstate::memory::{GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; use crate::vstate::vcpu::VcpuState; pub use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuEvent, VcpuHandle, VcpuResponse}; pub use crate::vstate::vm::Vm; @@ -520,12 +518,10 @@ impl Vmm { }; let device_states = self.mmio_device_manager.save(); - let memory_state = self.vm.guest_memory().describe(); let acpi_dev_state = self.acpi_device_manager.save(); Ok(MicrovmState { vm_info: vm_info.clone(), - memory_state, kvm_state, vm_state, vcpu_states, diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index ae58b329489..89703de2aba 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -76,8 +76,6 @@ impl From<&VmResources> for VmInfo { pub struct MicrovmState { /// Miscellaneous VM info. pub vm_info: VmInfo, - /// Memory state. - pub memory_state: GuestMemoryState, /// KVM KVM state. pub kvm_state: KvmState, /// VM KVM state. @@ -369,7 +367,7 @@ pub fn snapshot_state_sanity_check( // Check if the snapshot contains at least 1 mem region. // Upper bound check will be done when creating guest memory by comparing against // KVM max supported value kvm_context.max_memslots(). - if microvm_state.memory_state.regions.is_empty() { + if microvm_state.vm_state.memory.regions.is_empty() { return Err(SnapShotStateSanityCheckError::NoMemory); } @@ -452,7 +450,7 @@ pub fn restore_from_snapshot( snapshot_state_sanity_check(µvm_state)?; let mem_backend_path = ¶ms.mem_backend.backend_path; - let mem_state = µvm_state.memory_state; + let mem_state = µvm_state.vm_state.memory; let (guest_memory, uffd) = match params.mem_backend.backend_type { MemBackendType::File => { @@ -752,13 +750,11 @@ mod tests { assert!(states.vsock_device.is_some()); assert!(states.balloon_device.is_some()); - let memory_state = vmm.vm.guest_memory().describe(); let vcpu_states = vec![VcpuState::default()]; #[cfg(target_arch = "aarch64")] let mpidrs = construct_kvm_mpidrs(&vcpu_states); let microvm_state = MicrovmState { device_states: states, - memory_state, vcpu_states, kvm_state: Default::default(), vm_info: VmInfo { diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 6c1d094ff78..d9c5349b3a6 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -25,7 +25,8 @@ pub struct VmCommon { /// The KVM file descriptor used to access this Vm. pub fd: VmFd, max_memslots: usize, - guest_memory: GuestMemoryMmap, + /// The guest memory of this Vm. + pub guest_memory: GuestMemoryMmap, } /// Errors associated with the wrappers over KVM ioctls. diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index 7fe2c80d35d..d4efe77c57e 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -299,7 +299,7 @@ fn test_snapshot_load_sanity_checks() { snapshot_state_sanity_check(µvm_state).unwrap(); // Remove memory regions. - microvm_state.memory_state.regions.clear(); + microvm_state.vm_state.memory.regions.clear(); // Validate sanity checks fail because there is no mem region in state. assert_eq!( From d3f2539c4cd07154aff36804a2ebc3caf5501359 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 16:40:21 +0000 Subject: [PATCH 455/464] refactor: move dirty bitmap functions into struct Vm Now that guest memory is tracked inside struct Vm instead of struct Vmm, the dirty bitmap tracking functions can also start living in struct Vm. While we're touching it anyway, update the types used to kvm memslot numbers to be the native u32. This saves us a few ugly usize->u32 cast. Also change the error type as to not drag in VmmError into the vm module, where it really doesn't belong. Signed-off-by: Patrick Roy --- src/vmm/src/lib.rs | 39 +++--------------------------- src/vmm/src/persist.rs | 8 +++--- src/vmm/src/vstate/memory.rs | 4 +-- src/vmm/src/vstate/vm.rs | 28 ++++++++++++++++++++- src/vmm/tests/integration_tests.rs | 15 +++++++----- 5 files changed, 45 insertions(+), 49 deletions(-) diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index eaa3cf1816f..29f3b0148ac 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -149,7 +149,6 @@ use crate::logger::{METRICS, MetricsError, error, info, warn}; use crate::persist::{MicrovmState, MicrovmStateError, VmInfo}; use crate::rate_limiter::BucketUpdate; use crate::snapshot::Persist; -use crate::utils::u64_to_usize; use crate::vmm_config::instance_info::{InstanceInfo, VmState}; use crate::vstate::memory::{GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; use crate::vstate::vcpu::VcpuState; @@ -263,7 +262,7 @@ pub enum VmmError { } /// Shorthand type for KVM dirty page bitmap. -pub type DirtyBitmap = HashMap>; +pub type DirtyBitmap = HashMap>; /// Returns the size of guest memory, in MiB. pub(crate) fn mem_size_mib(guest_memory: &GuestMemoryMmap) -> u64 { @@ -307,7 +306,8 @@ pub struct Vmm { // Guest VM core resources. kvm: Kvm, - vm: Vm, + /// VM object + pub vm: Vm, // Save UFFD in order to keep it open in the Firecracker process, as well. uffd: Option, vcpus_handles: Vec, @@ -586,39 +586,6 @@ impl Vmm { Ok(cpu_configs) } - /// Retrieves the KVM dirty bitmap for each of the guest's memory regions. - pub fn reset_dirty_bitmap(&self) { - self.vm - .guest_memory() - .iter() - .enumerate() - .for_each(|(slot, region)| { - let _ = self - .vm - .fd() - .get_dirty_log(u32::try_from(slot).unwrap(), u64_to_usize(region.len())); - }); - } - - /// Retrieves the KVM dirty bitmap for each of the guest's memory regions. - pub fn get_dirty_bitmap(&self) -> Result { - let mut bitmap: DirtyBitmap = HashMap::new(); - self.vm - .guest_memory() - .iter() - .enumerate() - .try_for_each(|(slot, region)| { - let bitmap_region = self - .vm - .fd() - .get_dirty_log(u32::try_from(slot).unwrap(), u64_to_usize(region.len()))?; - bitmap.insert(slot, bitmap_region); - Ok(()) - }) - .map_err(VmmError::DirtyBitmap)?; - Ok(bitmap) - } - /// Updates the path of the host file backing the emulated block device with id `drive_id`. /// We update the disk image on the device and its virtio configuration. pub fn update_block_device_path( diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 89703de2aba..3b5add1c5c4 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -42,7 +42,7 @@ use crate::vstate::memory; use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState, GuestRegionMmap, MemoryError}; use crate::vstate::vcpu::{VcpuSendEventError, VcpuState}; use crate::vstate::vm::VmState; -use crate::{EventManager, Vmm, VmmError, mem_size_mib, vstate}; +use crate::{EventManager, Vmm, mem_size_mib, vstate}; /// Holds information related to the VM that is not part of VmState. #[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] @@ -136,7 +136,7 @@ pub enum MicrovmStateError { #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum CreateSnapshotError { /// Cannot get dirty bitmap: {0} - DirtyBitmap(VmmError), + DirtyBitmap(vmm_sys_util::errno::Error), /// Cannot write memory file: {0} Memory(MemoryError), /// Cannot perform {0} on the memory backing file: {1} @@ -245,7 +245,7 @@ fn snapshot_memory_to_file( match snapshot_type { SnapshotType::Diff => { - let dirty_bitmap = vmm.get_dirty_bitmap().map_err(DirtyBitmap)?; + let dirty_bitmap = vmm.vm.get_dirty_bitmap().map_err(DirtyBitmap)?; vmm.vm .guest_memory() .dump_dirty(&mut file, &dirty_bitmap) @@ -254,7 +254,7 @@ fn snapshot_memory_to_file( SnapshotType::Full => { let dump_res = vmm.vm.guest_memory().dump(&mut file).map_err(Memory); if dump_res.is_ok() { - vmm.reset_dirty_bitmap(); + vmm.vm.reset_dirty_bitmap(); vmm.vm.guest_memory().reset_dirty(); } diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index aaf51490738..19367f7f997 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -227,7 +227,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { let mut writer_offset = 0; let page_size = get_page_size().map_err(MemoryError::PageSize)?; - let write_result = self.iter().enumerate().try_for_each(|(slot, region)| { + let write_result = self.iter().zip(0..).try_for_each(|(region, slot)| { let kvm_bitmap = dirty_bitmap.get(&slot).unwrap(); let firecracker_bitmap = region.bitmap(); let mut write_size = 0; @@ -291,7 +291,7 @@ impl GuestMemoryExtension for GuestMemoryMmap { /// Stores the dirty bitmap inside into the internal bitmap fn store_dirty_bitmap(&self, dirty_bitmap: &DirtyBitmap, page_size: usize) { - self.iter().enumerate().for_each(|(slot, region)| { + self.iter().zip(0..).for_each(|(region, slot)| { let kvm_bitmap = dirty_bitmap.get(&slot).unwrap(); let firecracker_bitmap = region.bitmap(); diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index d9c5349b3a6..1728c5ec97a 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -5,19 +5,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. +use std::collections::HashMap; use std::sync::Arc; use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region}; use kvm_ioctls::VmFd; use vmm_sys_util::eventfd::EventFd; -use crate::Vcpu; pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState}; use crate::logger::info; +use crate::utils::u64_to_usize; use crate::vstate::memory::{ Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap, }; use crate::vstate::vcpu::VcpuError; +use crate::{DirtyBitmap, Vcpu}; /// Architecture independent parts of a VM. #[derive(Debug)] @@ -177,6 +179,30 @@ impl Vm { pub fn guest_memory(&self) -> &GuestMemoryMmap { &self.common.guest_memory } + + /// Resets the KVM dirty bitmap for each of the guest's memory regions. + pub fn reset_dirty_bitmap(&self) { + self.guest_memory() + .iter() + .zip(0u32..) + .for_each(|(region, slot)| { + let _ = self.fd().get_dirty_log(slot, u64_to_usize(region.len())); + }); + } + + /// Retrieves the KVM dirty bitmap for each of the guest's memory regions. + pub fn get_dirty_bitmap(&self) -> Result { + let mut bitmap: DirtyBitmap = HashMap::new(); + self.guest_memory() + .iter() + .zip(0u32..) + .try_for_each(|(region, slot)| { + self.fd() + .get_dirty_log(slot, u64_to_usize(region.len())) + .map(|bitmap_region| _ = bitmap.insert(slot, bitmap_region)) + })?; + Ok(bitmap) + } } #[cfg(test)] diff --git a/src/vmm/tests/integration_tests.rs b/src/vmm/tests/integration_tests.rs index d4efe77c57e..55fb07c1aae 100644 --- a/src/vmm/tests/integration_tests.rs +++ b/src/vmm/tests/integration_tests.rs @@ -14,8 +14,6 @@ use vmm::rpc_interface::{ }; use vmm::seccomp::get_empty_filters; use vmm::snapshot::Snapshot; -#[cfg(target_arch = "x86_64")] -use vmm::test_utils::dirty_tracking_vmm; use vmm::test_utils::mock_resources::{MockVmResources, NOISY_KERNEL_IMAGE}; use vmm::test_utils::{create_vmm, default_vmm, default_vmm_no_boot}; use vmm::vmm_config::balloon::BalloonDeviceConfig; @@ -112,8 +110,13 @@ fn test_dirty_bitmap_error() { // with errno 2 (ENOENT) because KVM can't find any guest memory regions with dirty // page tracking enabled. assert_eq!( - format!("{:?}", vmm.lock().unwrap().get_dirty_bitmap().err()), - "Some(DirtyBitmap(Error(2)))" + vmm.lock() + .unwrap() + .vm + .get_dirty_bitmap() + .unwrap_err() + .errno(), + 2 ); vmm.lock().unwrap().stop(FcExitCode::Ok); } @@ -122,11 +125,11 @@ fn test_dirty_bitmap_error() { #[cfg(target_arch = "x86_64")] fn test_dirty_bitmap_success() { // The vmm will start with dirty page tracking = ON. - let (vmm, _) = dirty_tracking_vmm(Some(NOISY_KERNEL_IMAGE)); + let (vmm, _) = vmm::test_utils::dirty_tracking_vmm(Some(NOISY_KERNEL_IMAGE)); // Let it churn for a while and dirty some pages... thread::sleep(Duration::from_millis(100)); - let bitmap = vmm.lock().unwrap().get_dirty_bitmap().unwrap(); + let bitmap = vmm.lock().unwrap().vm.get_dirty_bitmap().unwrap(); let num_dirty_pages: u32 = bitmap .values() .map(|bitmap_per_region| { From e026e54f254512325b3ee0015671a729b9cf15a8 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 16:42:50 +0000 Subject: [PATCH 456/464] refactor: hoist post-snapshot vring re-dirtying Do this in create_snapshot() instead of snapshot_memory_to_file(), as it was the only operation inside snapshot_memory_to_file() that required access to a struct Vmm, opening the gates for move the rest of snapshot_memory_to_file() into struct Vm. Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 3b5add1c5c4..7e363f16a96 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -166,6 +166,23 @@ pub fn create_snapshot( snapshot_memory_to_file(vmm, ¶ms.mem_file_path, params.snapshot_type)?; + // We need to mark queues as dirty again for all activated devices. The reason we + // do it here is because we don't mark pages as dirty during runtime + // for queue objects. + // SAFETY: + // This should never fail as we only mark pages only if device has already been activated, + // and the address validation was already performed on device activation. + vmm.mmio_device_manager + .for_each_virtio_device(|_, _, _, dev| { + let d = dev.lock().unwrap(); + if d.is_activated() { + d.mark_queue_memory_dirty(vmm.vm.guest_memory()) + } else { + Ok(()) + } + }) + .unwrap(); + Ok(()) } @@ -261,22 +278,6 @@ fn snapshot_memory_to_file( dump_res } }?; - // We need to mark queues as dirty again for all activated devices. The reason we - // do it here is because we don't mark pages as dirty during runtime - // for queue objects. - // SAFETY: - // This should never fail as we only mark pages only if device has already been activated, - // and the address validation was already performed on device activation. - vmm.mmio_device_manager - .for_each_virtio_device(|_, _, _, dev| { - let d = dev.lock().unwrap(); - if d.is_activated() { - d.mark_queue_memory_dirty(vmm.vm.guest_memory()) - } else { - Ok(()) - } - }) - .unwrap(); file.flush() .map_err(|err| MemoryBackingFile("flush", err))?; From 12fa176bb6b37732f8c8f816d9fe73ec06289c96 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 26 Mar 2025 16:54:08 +0000 Subject: [PATCH 457/464] refactor: move snapshot_memory_to_file into struct Vm struct Vm encapsulates the memory, so having this function live there makes sense. It also prepares us for the future where multiple GuestMemoryMmap objects need to be managed. Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 86 +++------------------------------------- src/vmm/src/vstate/vm.rs | 83 +++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 83 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 7e363f16a96..b57105709cb 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -34,15 +34,13 @@ use crate::utils::u64_to_usize; use crate::vmm_config::boot_source::BootSourceConfig; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{HugePageConfig, MachineConfigError, MachineConfigUpdate}; -use crate::vmm_config::snapshot::{ - CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType, -}; +use crate::vmm_config::snapshot::{CreateSnapshotParams, LoadSnapshotParams, MemBackendType}; use crate::vstate::kvm::KvmState; use crate::vstate::memory; -use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState, GuestRegionMmap, MemoryError}; +use crate::vstate::memory::{GuestMemoryState, GuestRegionMmap, MemoryError}; use crate::vstate::vcpu::{VcpuSendEventError, VcpuState}; use crate::vstate::vm::VmState; -use crate::{EventManager, Vmm, mem_size_mib, vstate}; +use crate::{EventManager, Vmm, vstate}; /// Holds information related to the VM that is not part of VmState. #[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] @@ -164,7 +162,8 @@ pub fn create_snapshot( snapshot_state_to_file(µvm_state, ¶ms.snapshot_path)?; - snapshot_memory_to_file(vmm, ¶ms.mem_file_path, params.snapshot_type)?; + vmm.vm + .snapshot_memory_to_file(¶ms.mem_file_path, params.snapshot_type)?; // We need to mark queues as dirty again for all activated devices. The reason we // do it here is because we don't mark pages as dirty during runtime @@ -210,81 +209,6 @@ fn snapshot_state_to_file( .map_err(|err| SnapshotBackingFile("sync_all", err)) } -/// Takes a snapshot of the virtual machine running inside the given [`Vmm`] and saves it to -/// `mem_file_path`. -/// -/// If `snapshot_type` is [`SnapshotType::Diff`], and `mem_file_path` exists and is a snapshot file -/// of matching size, then the diff snapshot will be directly merged into the existing snapshot. -/// Otherwise, existing files are simply overwritten. -fn snapshot_memory_to_file( - vmm: &Vmm, - mem_file_path: &Path, - snapshot_type: SnapshotType, -) -> Result<(), CreateSnapshotError> { - use self::CreateSnapshotError::*; - - // Need to check this here, as we create the file in the line below - let file_existed = mem_file_path.exists(); - - let mut file = OpenOptions::new() - .write(true) - .create(true) - .truncate(false) - .open(mem_file_path) - .map_err(|err| MemoryBackingFile("open", err))?; - - // Determine what size our total memory area is. - let mem_size_mib = mem_size_mib(vmm.vm.guest_memory()); - let expected_size = mem_size_mib * 1024 * 1024; - - if file_existed { - let file_size = file - .metadata() - .map_err(|e| MemoryBackingFile("get_metadata", e))? - .len(); - - // Here we only truncate the file if the size mismatches. - // - For full snapshots, the entire file's contents will be overwritten anyway. We have to - // avoid truncating here to deal with the edge case where it represents the snapshot file - // from which this very microVM was loaded (as modifying the memory file would be - // reflected in the mmap of the file, meaning a truncate operation would zero out guest - // memory, and thus corrupt the VM). - // - For diff snapshots, we want to merge the diff layer directly into the file. - if file_size != expected_size { - file.set_len(0) - .map_err(|err| MemoryBackingFile("truncate", err))?; - } - } - - // Set the length of the file to the full size of the memory area. - file.set_len(expected_size) - .map_err(|e| MemoryBackingFile("set_length", e))?; - - match snapshot_type { - SnapshotType::Diff => { - let dirty_bitmap = vmm.vm.get_dirty_bitmap().map_err(DirtyBitmap)?; - vmm.vm - .guest_memory() - .dump_dirty(&mut file, &dirty_bitmap) - .map_err(Memory) - } - SnapshotType::Full => { - let dump_res = vmm.vm.guest_memory().dump(&mut file).map_err(Memory); - if dump_res.is_ok() { - vmm.vm.reset_dirty_bitmap(); - vmm.vm.guest_memory().reset_dirty(); - } - - dump_res - } - }?; - - file.flush() - .map_err(|err| MemoryBackingFile("flush", err))?; - file.sync_all() - .map_err(|err| MemoryBackingFile("sync_all", err)) -} - /// Validates that snapshot CPU vendor matches the host CPU vendor. /// /// # Errors diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 1728c5ec97a..32627530a4b 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -6,6 +6,9 @@ // found in the THIRD-PARTY file. use std::collections::HashMap; +use std::fs::OpenOptions; +use std::io::Write; +use std::path::Path; use std::sync::Arc; use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region}; @@ -14,12 +17,14 @@ use vmm_sys_util::eventfd::EventFd; pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState}; use crate::logger::info; +use crate::persist::CreateSnapshotError; use crate::utils::u64_to_usize; +use crate::vmm_config::snapshot::SnapshotType; use crate::vstate::memory::{ - Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap, + Address, GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap, }; use crate::vstate::vcpu::VcpuError; -use crate::{DirtyBitmap, Vcpu}; +use crate::{DirtyBitmap, Vcpu, mem_size_mib}; /// Architecture independent parts of a VM. #[derive(Debug)] @@ -203,6 +208,80 @@ impl Vm { })?; Ok(bitmap) } + + /// Takes a snapshot of the virtual machine running inside the given [`Vmm`] and saves it to + /// `mem_file_path`. + /// + /// If `snapshot_type` is [`SnapshotType::Diff`], and `mem_file_path` exists and is a snapshot + /// file of matching size, then the diff snapshot will be directly merged into the existing + /// snapshot. Otherwise, existing files are simply overwritten. + pub(crate) fn snapshot_memory_to_file( + &self, + mem_file_path: &Path, + snapshot_type: SnapshotType, + ) -> Result<(), CreateSnapshotError> { + use self::CreateSnapshotError::*; + + // Need to check this here, as we create the file in the line below + let file_existed = mem_file_path.exists(); + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(false) + .open(mem_file_path) + .map_err(|err| MemoryBackingFile("open", err))?; + + // Determine what size our total memory area is. + let mem_size_mib = mem_size_mib(self.guest_memory()); + let expected_size = mem_size_mib * 1024 * 1024; + + if file_existed { + let file_size = file + .metadata() + .map_err(|e| MemoryBackingFile("get_metadata", e))? + .len(); + + // Here we only truncate the file if the size mismatches. + // - For full snapshots, the entire file's contents will be overwritten anyway. We have + // to avoid truncating here to deal with the edge case where it represents the + // snapshot file from which this very microVM was loaded (as modifying the memory file + // would be reflected in the mmap of the file, meaning a truncate operation would zero + // out guest memory, and thus corrupt the VM). + // - For diff snapshots, we want to merge the diff layer directly into the file. + if file_size != expected_size { + file.set_len(0) + .map_err(|err| MemoryBackingFile("truncate", err))?; + } + } + + // Set the length of the file to the full size of the memory area. + file.set_len(expected_size) + .map_err(|e| MemoryBackingFile("set_length", e))?; + + match snapshot_type { + SnapshotType::Diff => { + let dirty_bitmap = self.get_dirty_bitmap().map_err(DirtyBitmap)?; + self.guest_memory() + .dump_dirty(&mut file, &dirty_bitmap) + .map_err(Memory) + } + SnapshotType::Full => { + let dump_res = self.guest_memory().dump(&mut file).map_err(Memory); + if dump_res.is_ok() { + self.reset_dirty_bitmap(); + self.guest_memory().reset_dirty(); + } + + dump_res + } + }?; + + file.flush() + .map_err(|err| MemoryBackingFile("flush", err))?; + file.sync_all() + .map_err(|err| MemoryBackingFile("sync_all", err)) + } } #[cfg(test)] From 768440e4446a8d816a344e88039b239da425238b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 28 Mar 2025 12:02:54 +0000 Subject: [PATCH 458/464] refactor: #[from]-ify CreateSnapshotError Avoid some .map_err() calls using #[from] and the auto-From::from calling of the question mark operator. Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 10 ++++------ src/vmm/src/vstate/vm.rs | 8 +++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index b57105709cb..35bb84ed208 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -134,15 +134,15 @@ pub enum MicrovmStateError { #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum CreateSnapshotError { /// Cannot get dirty bitmap: {0} - DirtyBitmap(vmm_sys_util::errno::Error), + DirtyBitmap(#[from] vmm_sys_util::errno::Error), /// Cannot write memory file: {0} - Memory(MemoryError), + Memory(#[from] MemoryError), /// Cannot perform {0} on the memory backing file: {1} MemoryBackingFile(&'static str, io::Error), /// Cannot save the microVM state: {0} MicrovmState(MicrovmStateError), /// Cannot serialize the microVM state: {0} - SerializeMicrovmState(crate::snapshot::SnapshotError), + SerializeMicrovmState(#[from] crate::snapshot::SnapshotError), /// Cannot perform {0} on the snapshot backing file: {1} SnapshotBackingFile(&'static str, io::Error), } @@ -198,9 +198,7 @@ fn snapshot_state_to_file( .map_err(|err| SnapshotBackingFile("open", err))?; let snapshot = Snapshot::new(SNAPSHOT_VERSION); - snapshot - .save(&mut snapshot_file, microvm_state) - .map_err(SerializeMicrovmState)?; + snapshot.save(&mut snapshot_file, microvm_state)?; snapshot_file .flush() .map_err(|err| SnapshotBackingFile("flush", err))?; diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 32627530a4b..cf038c6574a 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -261,13 +261,11 @@ impl Vm { match snapshot_type { SnapshotType::Diff => { - let dirty_bitmap = self.get_dirty_bitmap().map_err(DirtyBitmap)?; - self.guest_memory() - .dump_dirty(&mut file, &dirty_bitmap) - .map_err(Memory) + let dirty_bitmap = self.get_dirty_bitmap()?; + self.guest_memory().dump_dirty(&mut file, &dirty_bitmap) } SnapshotType::Full => { - let dump_res = self.guest_memory().dump(&mut file).map_err(Memory); + let dump_res = self.guest_memory().dump(&mut file); if dump_res.is_ok() { self.reset_dirty_bitmap(); self.guest_memory().reset_dirty(); From 752efcb712ef247fb2a8bf444f562c5064ce6f23 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 31 Mar 2025 12:04:24 +0100 Subject: [PATCH 459/464] refactor: cleanup error propagation in snapshot_emory_to_file We can just immediately propagate errors to the caller using `?` syntax, which saves us the "if (...).is_ok()" check. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vm.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index cf038c6574a..7a8965a4b9a 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -262,18 +262,14 @@ impl Vm { match snapshot_type { SnapshotType::Diff => { let dirty_bitmap = self.get_dirty_bitmap()?; - self.guest_memory().dump_dirty(&mut file, &dirty_bitmap) + self.guest_memory().dump_dirty(&mut file, &dirty_bitmap)?; } SnapshotType::Full => { - let dump_res = self.guest_memory().dump(&mut file); - if dump_res.is_ok() { - self.reset_dirty_bitmap(); - self.guest_memory().reset_dirty(); - } - - dump_res + self.guest_memory().dump(&mut file)?; + self.reset_dirty_bitmap(); + self.guest_memory().reset_dirty(); } - }?; + }; file.flush() .map_err(|err| MemoryBackingFile("flush", err))?; From ea1124e3243aed3f1ddd71e005e55f9537bc7e77 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Fri, 28 Mar 2025 16:59:32 +0000 Subject: [PATCH 460/464] fix: print inner error in case of PersistError::QueueConstruction Otherwise it's impossible to figure out what precisely went wrong during queue restoration. Signed-off-by: Patrick Roy --- src/vmm/src/devices/virtio/persist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm/src/devices/virtio/persist.rs b/src/vmm/src/devices/virtio/persist.rs index 7551921f4b0..7c861352317 100644 --- a/src/vmm/src/devices/virtio/persist.rs +++ b/src/vmm/src/devices/virtio/persist.rs @@ -22,7 +22,7 @@ use crate::vstate::memory::{GuestAddress, GuestMemoryMmap}; pub enum PersistError { /// Snapshot state contains invalid queue info. InvalidInput, - /// Could not restore queue. + /// Could not restore queue: {0} QueueConstruction(QueueError), } From d26fc1c75717459715ece0095b6ed27d6ca4a278 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Wed, 29 Jan 2025 16:23:16 +0000 Subject: [PATCH 461/464] add offset argument to `arch_regions` This allows having regions that start somewhere other than guest physical address 0. Useful in case not all regions are allocated at once, and each batch needs to be placed after all already allocated regions. Since the resulting code has some intricacies (and I actually got it wrong the first time around), write a kani harness to validate that we're computing the regions correctly. On ARM, add a warning in case we hit some questionable logic around truncation of memory sizes if they exceed architectural bounds (although if anyone is hitting this, they're already doing something wrong anyway, because it'd require a VM with more than 1022GiB of memory). Signed-off-by: Patrick Roy --- src/vmm/src/arch/aarch64/mod.rs | 77 +++++++++++++++++++++-- src/vmm/src/arch/x86_64/mod.rs | 105 +++++++++++++++++++++++++++++--- src/vmm/src/resources.rs | 2 +- src/vmm/src/test_utils/mod.rs | 4 +- 4 files changed, 171 insertions(+), 17 deletions(-) diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 99c2acf2f54..ead827c08c4 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -32,7 +32,7 @@ use crate::utils::{align_up, usize_to_u64}; use crate::vmm_config::machine_config::MachineConfig; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; use crate::vstate::vcpu::KvmVcpuError; -use crate::{Vcpu, VcpuConfig, Vmm}; +use crate::{Vcpu, VcpuConfig, Vmm, logger}; /// Errors thrown while configuring aarch64 system. #[derive(Debug, thiserror::Error, displaydoc::Display)] @@ -58,9 +58,35 @@ pub const MMIO_MEM_SIZE: u64 = layout::DRAM_MEM_START - layout::MAPPED_IO_START; /// Returns a Vec of the valid memory addresses for aarch64. /// See [`layout`](layout) module for a drawing of the specific memory model for this platform. -pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> { - let dram_size = min(size, layout::DRAM_MEM_MAX_SIZE); - vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)] +/// +/// The `offset` parameter specified the offset from [`layout::DRAM_MEM_START`]. +pub fn arch_memory_regions(offset: usize, size: usize) -> Vec<(GuestAddress, usize)> { + assert!(size > 0, "Attempt to allocate guest memory of length 0"); + assert!( + offset.checked_add(size).is_some(), + "Attempt to allocate guest memory such that the address space would wrap around" + ); + assert!( + offset < layout::DRAM_MEM_MAX_SIZE, + "offset outside allowed DRAM range" + ); + + let dram_size = min(size, layout::DRAM_MEM_MAX_SIZE - offset); + + if dram_size != size { + logger::warn!( + "Requested offset/memory size {}/{} exceeds architectural maximum (1022GiB). Size has \ + been truncated to {}", + offset, + size, + dram_size + ); + } + + vec![( + GuestAddress(layout::DRAM_MEM_START + offset as u64), + dram_size, + )] } /// Configures the system for booting Linux. @@ -184,6 +210,45 @@ pub fn load_kernel( }) } +#[cfg(kani)] +mod verification { + use vm_memory::GuestAddress; + + use crate::arch::aarch64::layout; + use crate::arch::arch_memory_regions; + + #[kani::proof] + #[kani::unwind(3)] + fn verify_arch_memory_regions() { + let offset: u64 = kani::any::(); + let len: u64 = kani::any::(); + + kani::assume(len > 0); + kani::assume(offset.checked_add(len).is_some()); + kani::assume(offset < layout::DRAM_MEM_MAX_SIZE as u64); + + let regions = arch_memory_regions(offset as usize, len as usize); + + // No MMIO gap on ARM + assert_eq!(regions.len(), 1); + + let (GuestAddress(start), actual_len) = regions[0]; + let actual_len = actual_len as u64; + + assert_eq!(start, layout::DRAM_MEM_START + offset); + assert!(actual_len <= layout::DRAM_MEM_MAX_SIZE as u64); + assert!(actual_len <= len); + + if actual_len < len { + assert_eq!( + start + actual_len, + layout::DRAM_MEM_START + layout::DRAM_MEM_MAX_SIZE as u64 + ); + assert!(offset + len >= layout::DRAM_MEM_MAX_SIZE as u64); + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -191,7 +256,7 @@ mod tests { #[test] fn test_regions_lt_1024gb() { - let regions = arch_memory_regions(1usize << 29); + let regions = arch_memory_regions(0, 1usize << 29); assert_eq!(1, regions.len()); assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0); assert_eq!(1usize << 29, regions[0].1); @@ -199,7 +264,7 @@ mod tests { #[test] fn test_regions_gt_1024gb() { - let regions = arch_memory_regions(1usize << 41); + let regions = arch_memory_regions(0, 1usize << 41); assert_eq!(1, regions.len()); assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0); assert_eq!(super::layout::DRAM_MEM_MAX_SIZE, regions[0].1); diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 30c98a0cbd3..ca350cbf9af 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -110,17 +110,33 @@ pub const MMIO_MEM_SIZE: u64 = MEM_32BIT_GAP_SIZE; /// These should be used to configure the GuestMemoryMmap structure for the platform. /// For x86_64 all addresses are valid from the start of the kernel except a /// carve out at the end of 32bit address space. -pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> { +pub fn arch_memory_regions(offset: usize, size: usize) -> Vec<(GuestAddress, usize)> { + // If we get here with size == 0 something has seriously gone wrong. Firecracker should never + // try to allocate guest memory of size 0 + assert!(size > 0, "Attempt to allocate guest memory of length 0"); + assert!( + offset.checked_add(size).is_some(), + "Attempt to allocate guest memory such that the address space would wrap around" + ); + // It's safe to cast MMIO_MEM_START to usize because it fits in a u32 variable // (It points to an address in the 32 bit space). - match size.checked_sub(usize::try_from(MMIO_MEM_START).unwrap()) { + match (size + offset).checked_sub(u64_to_usize(MMIO_MEM_START)) { // case1: guest memory fits before the gap - None | Some(0) => vec![(GuestAddress(0), size)], - // case2: guest memory extends beyond the gap - Some(remaining) => vec![ - (GuestAddress(0), usize::try_from(MMIO_MEM_START).unwrap()), + None | Some(0) => vec![(GuestAddress(offset as u64), size)], + // case2: starts before the gap, but doesn't completely fit + Some(remaining) if (offset as u64) < MMIO_MEM_START => vec![ + ( + GuestAddress(offset as u64), + u64_to_usize(MMIO_MEM_START) - offset, + ), (GuestAddress(FIRST_ADDR_PAST_32BITS), remaining), ], + // case3: guest memory start after the gap + Some(_) => vec![( + GuestAddress(FIRST_ADDR_PAST_32BITS.max(offset as u64)), + size, + )], } } @@ -456,6 +472,56 @@ pub fn load_kernel( }) } +#[cfg(kani)] +mod verification { + use crate::arch::x86_64::FIRST_ADDR_PAST_32BITS; + use crate::arch::{MMIO_MEM_START, arch_memory_regions}; + + #[kani::proof] + #[kani::unwind(3)] + fn verify_arch_memory_regions() { + let offset: u64 = kani::any::(); + let len: u64 = kani::any::(); + + kani::assume(len > 0); + kani::assume(offset.checked_add(len).is_some()); + + let regions = arch_memory_regions(offset as usize, len as usize); + + // There's only one MMIO gap, so we can get either 1 or 2 regions + assert!(regions.len() <= 2); + assert!(regions.len() >= 1); + + // The total length of all regions is what we requested + assert_eq!( + regions.iter().map(|&(_, len)| len).sum::(), + len as usize + ); + + // No region overlaps the MMIO gap + assert!( + regions + .iter() + .all(|&(start, len)| start.0 >= FIRST_ADDR_PAST_32BITS + || start.0 + len as u64 <= MMIO_MEM_START) + ); + + // All regions start after our specified offset + assert!(regions.iter().all(|&(start, _)| start.0 >= offset as u64)); + + // All regions have non-zero length + assert!(regions.iter().all(|&(_, len)| len > 0)); + + // If there's two regions, they perfectly snuggle up to the MMIO gap + if regions.len() == 2 { + kani::cover!(); + + assert_eq!(regions[0].0.0 + regions[0].1 as u64, MMIO_MEM_START); + assert_eq!(regions[1].0.0, FIRST_ADDR_PAST_32BITS); + } + } +} + #[cfg(test)] mod tests { use linux_loader::loader::bootparam::boot_e820_entry; @@ -466,18 +532,41 @@ mod tests { #[test] fn regions_lt_4gb() { - let regions = arch_memory_regions(1usize << 29); + let regions = arch_memory_regions(0, 1usize << 29); assert_eq!(1, regions.len()); assert_eq!(GuestAddress(0), regions[0].0); assert_eq!(1usize << 29, regions[0].1); + + let regions = arch_memory_regions(1 << 28, 1 << 29); + assert_eq!(1, regions.len()); + assert_eq!(regions[0], (GuestAddress(1 << 28), 1 << 29)); } #[test] fn regions_gt_4gb() { - let regions = arch_memory_regions((1usize << 32) + 0x8000); + const MEMORY_SIZE: usize = (1 << 32) + 0x8000; + + let regions = arch_memory_regions(0, MEMORY_SIZE); assert_eq!(2, regions.len()); assert_eq!(GuestAddress(0), regions[0].0); assert_eq!(GuestAddress(1u64 << 32), regions[1].0); + + let regions = arch_memory_regions(1 << 31, MEMORY_SIZE); + assert_eq!(2, regions.len()); + assert_eq!( + regions[0], + ( + GuestAddress(1 << 31), + u64_to_usize(MMIO_MEM_START) - (1 << 31) + ) + ); + assert_eq!( + regions[1], + ( + GuestAddress(FIRST_ADDR_PAST_32BITS), + MEMORY_SIZE - regions[0].1 + ) + ) } #[test] diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 98d71f4d0a6..097e2041b55 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -458,7 +458,7 @@ impl VmResources { // a single way of backing guest memory for vhost-user and non-vhost-user cases, // that would not be worth the effort. let regions = - crate::arch::arch_memory_regions(mib_to_bytes(self.machine_config.mem_size_mib)); + crate::arch::arch_memory_regions(0, mib_to_bytes(self.machine_config.mem_size_mib)); if vhost_user_device_used { memory::memfd_backed( regions.as_ref(), diff --git a/src/vmm/src/test_utils/mod.rs b/src/vmm/src/test_utils/mod.rs index d3700c98925..7cb16a2a213 100644 --- a/src/vmm/src/test_utils/mod.rs +++ b/src/vmm/src/test_utils/mod.rs @@ -58,11 +58,11 @@ pub fn multi_region_mem_raw(regions: &[(GuestAddress, usize)]) -> Vec GuestMemoryMmap { - multi_region_mem(&crate::arch::arch_memory_regions(mem_size_bytes)) + multi_region_mem(&crate::arch::arch_memory_regions(0, mem_size_bytes)) } pub fn arch_mem_raw(mem_size_bytes: usize) -> Vec { - multi_region_mem_raw(&crate::arch::arch_memory_regions(mem_size_bytes)) + multi_region_mem_raw(&crate::arch::arch_memory_regions(0, mem_size_bytes)) } pub fn create_vmm( From 85188a921a334303bd487ffc4936ee4bdb957a54 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Mar 2025 16:27:04 +0000 Subject: [PATCH 462/464] refactor: drop uffd parameter from create_vmm_and_vcpus This way the non-snapshot path doesnt have to deal with passing in `None`. Signed-off-by: Patrick Roy --- src/vmm/src/builder.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index a835930020e..27ba3e96fa9 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -134,7 +134,6 @@ impl std::convert::From for StartMicrovmError { fn create_vmm_and_vcpus( instance_info: &InstanceInfo, event_manager: &mut EventManager, - uffd: Option, vcpu_count: u8, kvm_capabilities: Vec, ) -> Result<(Vmm, Vec), VmmError> { @@ -177,7 +176,7 @@ fn create_vmm_and_vcpus( shutdown_exit_code: None, kvm, vm, - uffd, + uffd: None, vcpus_handles: Vec::new(), vcpus_exit_evt, resource_allocator, @@ -228,7 +227,6 @@ pub fn build_microvm_for_boot( let (mut vmm, mut vcpus) = create_vmm_and_vcpus( instance_info, event_manager, - None, vm_resources.machine_config.vcpu_count, cpu_template.kvm_capabilities.clone(), )?; @@ -424,7 +422,6 @@ pub fn build_microvm_from_snapshot( let (mut vmm, mut vcpus) = create_vmm_and_vcpus( instance_info, event_manager, - uffd, vm_resources.machine_config.vcpu_count, microvm_state.kvm_state.kvm_cap_modifiers.clone(), ) @@ -434,6 +431,7 @@ pub fn build_microvm_from_snapshot( .register_memory_regions(guest_memory) .map_err(VmmError::Vm) .map_err(StartMicrovmError::Internal)?; + vmm.uffd = uffd; #[cfg(target_arch = "x86_64")] { From 5ac1442340dd829f966a3b6da0c910cbbb793cc1 Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Tue, 25 Mar 2025 16:53:15 +0000 Subject: [PATCH 463/464] uffd: unconditionally enable UFFD_FEATURE_EVENT_REMOVE Only enabling it when a balloon device is present doesn't really gain us anything, because the only time this feature is checked in the kernel is as part of madvise handling - but without balloon devices we wont ever call madvise, so it makes no difference whether we enabled the feature or not (it is unconditionally available since linux 4.10). Signed-off-by: Patrick Roy --- src/vmm/src/persist.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 35bb84ed208..be2fbc0a040 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -393,9 +393,6 @@ pub fn restore_from_snapshot( mem_backend_path, mem_state, track_dirty_pages, - // We enable the UFFD_FEATURE_EVENT_REMOVE feature only if a balloon device - // is present in the microVM state. - microvm_state.device_states.balloon_device.is_some(), vm_resources.machine_config.huge_pages, ) .map_err(RestoreFromSnapshotGuestMemoryError::Uffd)?, @@ -479,7 +476,6 @@ fn guest_memory_from_uffd( mem_uds_path: &Path, mem_state: &GuestMemoryState, track_dirty_pages: bool, - enable_balloon: bool, huge_pages: HugePageConfig, ) -> Result<(Vec, Option), GuestMemoryFromUffdError> { let (guest_memory, backend_mappings) = @@ -487,11 +483,11 @@ fn guest_memory_from_uffd( let mut uffd_builder = UffdBuilder::new(); - if enable_balloon { - // We enable this so that the page fault handler can add logic - // for treating madvise(MADV_DONTNEED) events triggerd by balloon inflation. - uffd_builder.require_features(FeatureFlags::EVENT_REMOVE); - } + // We only make use of this if balloon devices are present, but we can enable it unconditionally + // because the only place the kernel checks this is in a hook from madvise, e.g. it doesn't + // actively change the behavior of UFFD, only passively. Without balloon devices + // we never call madvise anyway, so no need to put this into a conditional. + uffd_builder.require_features(FeatureFlags::EVENT_REMOVE); let uffd = uffd_builder .close_on_exec(true) From 45fc21bcddc17212c22d639096f81ff97c9a344b Mon Sep 17 00:00:00 2001 From: Patrick Roy Date: Mon, 31 Mar 2025 13:14:54 +0100 Subject: [PATCH 464/464] fix(test): do not drop Vm object before end of test Dropping the VM object closes the VM FD, which can cause the test to hang. Signed-off-by: Patrick Roy --- src/vmm/src/vstate/vcpu.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vmm/src/vstate/vcpu.rs b/src/vmm/src/vstate/vcpu.rs index 5d9afca3255..825af33eea4 100644 --- a/src/vmm/src/vstate/vcpu.rs +++ b/src/vmm/src/vstate/vcpu.rs @@ -958,7 +958,7 @@ pub(crate) mod tests { entry_addr.kernel_load } - fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd) { + fn vcpu_configured_for_boot() -> (Vm, VcpuHandle, EventFd) { Vcpu::register_kick_signal_handler(); // Need enough mem to boot linux. let mem_size = mib_to_bytes(64); @@ -1013,7 +1013,7 @@ pub(crate) mod tests { // Wait for vCPUs to initialize their TLS before moving forward. barrier.wait(); - (vcpu_handle, vcpu_exit_evt) + (vm, vcpu_handle, vcpu_exit_evt) } #[test] @@ -1147,7 +1147,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_pause_resume() { - let (vcpu_handle, vcpu_exit_evt) = vcpu_configured_for_boot(); + let (_vm, vcpu_handle, vcpu_exit_evt) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1179,7 +1179,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_save_state_events() { - let (vcpu_handle, _vcpu_exit_evt) = vcpu_configured_for_boot(); + let (_vm, vcpu_handle, _vcpu_exit_evt) = vcpu_configured_for_boot(); // Queue a Resume event, expect a response. queue_event_expect_response(&vcpu_handle, VcpuEvent::Resume, VcpuResponse::Resumed); @@ -1212,7 +1212,7 @@ pub(crate) mod tests { #[test] fn test_vcpu_dump_cpu_config() { - let (vcpu_handle, _) = vcpu_configured_for_boot(); + let (_vm, vcpu_handle, _) = vcpu_configured_for_boot(); // Queue a DumpCpuConfig event, expect a DumpedCpuConfig response. vcpu_handle