diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3d8b419fc..051addd332d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to ### Added +- [#4687](https://github.com/firecracker-microvm/firecracker/pull/4687): Added + 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. + ### Changed ### Deprecated diff --git a/docs/snapshotting/random-for-clones.md b/docs/snapshotting/random-for-clones.md index 18f0cf452d3..103090a7d56 100644 --- a/docs/snapshotting/random-for-clones.md +++ b/docs/snapshotting/random-for-clones.md @@ -43,8 +43,6 @@ and there’s also an input pool which gathers entropy from various sources available on the system, and is used to feed into or seed the other two components. A very detailed description is available [here][3]. -### Linux kernels from 4.8 until 5.17 (included) - The details of this newer implementation are used to make the recommendations present in the document. There are in-kernel interfaces used to obtain random numbers as well, but they are similar to using `/dev/urandom` (or `getrandom` @@ -103,15 +101,17 @@ not increase the current entropy estimation. There is also an `ioctl` interface which, given the appropriate privileges, can be used to add data to the input entropy pool while also increasing the count, or completely empty all pools. -### Linux kernels from 5.18 onwards - -Since version 5.18, Linux has support for the -[Virtual Machine Generation Identifier](https://learn.microsoft.com/en-us/windows/win32/hyperv_v2/virtual-machine-generation-identifier). -The purpose of VMGenID is to notify the guest about time shift events, such as -resuming from a snapshot. The device exposes a 16-byte cryptographically random -identifier in guest memory. Firecracker implements VMGenID. When resuming a -microVM from a snapshot Firecracker writes a new identifier and injects a -notification to the guest. Linux, +### Linux kernels with VMGenID support + +Linux has support for the +[Virtual Machine Generation Identifier](https://learn.microsoft.com/en-us/windows/win32/hyperv_v2/virtual-machine-generation-identifier) +since 5.18 for ACPI systems. Since 6.10, Linux added support also for systems +that use DeviceTree instead of ACPI. The purpose of VMGenID is to notify the +guest about time shift events, such as resuming from a snapshot. The device +exposes a 16-byte cryptographically random identifier in guest memory. +Firecracker implements VMGenID. When resuming a microVM from a snapshot +Firecracker writes a new identifier and injects a notification to the guest. +Linux, [uses this value](https://elixir.bootlin.com/linux/v5.18.19/source/drivers/virt/vmgenid.c#L77) [as new randomness for its CSPRNG](https://elixir.bootlin.com/linux/v5.18.19/source/drivers/char/random.c#L908). Quoting the random.c implementation of the kernel: @@ -133,9 +133,15 @@ to emit a uevent to user space when it handles the notification. User space can poll this uevent to know when it is safe to use `getrandom()`, et al. avoiding the race condition. -Please note that, Firecracker will always enable VMGenID. In kernels earlier -than 5.18, where there is no VMGenID driver, the device will not have any effect -in the guest. +Firecracker supports VMGenID on ARM systems using the DeviceTree binding that +was added for the device in Linux 6.10. However, the latest Linux kernel that +Firecracker supports is 6.1. As a result, in order to use VMGenID on ARM +systems, users need to use a 6.1 kernel with the DeviceTree binding support +backported from 6.10. We provide a set of patches that apply cleanly on mainline +Linux 6.1 [here](../../resources/patches/vmgenid_dt). + +Please note that, Firecracker will always enable VMGenID. In kernels where there +is no VMGenID driver, the device will not have any effect in the guest. ### User space considerations diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 5e5e72cec97..3119ffcc264 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -584,18 +584,18 @@ we also consider microVM A insecure if it resumes execution. (VMGenID) is a virtual device that allows VM guests to detect when they have resumed from a snapshot. It works by exposing a cryptographically random 16-bytes identifier to the guest. The VMM ensures that the value of the -indentifier changes every time the VM a time shift happens in the lifecycle of +identifier changes every time the VM a time shift happens in the lifecycle of the VM, e.g. when it resumes from a snapshot. -Linux supports VMGenID since version 5.18. When Linux detects a change in the -identifier, it uses its value to reseed its internal PRNG. Moreover, -[since version 6.8](https://lkml.org/lkml/2023/5/31/414) Linux VMGenID driver -also emits to userspace a uevent. User space processes can monitor this uevent -for detecting snapshot resume events. +Linux supports VMGenID since version 5.18 for systems with ACPI support. Linux +6.10 added support also for systems that use DeviceTree instead of ACPI. When +Linux detects a change in the identifier, it uses its value to reseed its +internal PRNG. -Firecracker supports VMGenID device on x86 platforms. Firecracker will always -enable the device. During snapshot resume, Firecracker will update the 16-byte -generation ID and inject a notification in the guest before resuming its vCPUs. +Firecracker supports VMGenID device both on x86 and Aarch64 platforms. +Firecracker will always enable the device. During snapshot resume, Firecracker +will update the 16-byte generation ID and inject a notification in the guest +before resuming its vCPUs. As a result, guests that run Linux versions >= 5.18 will re-seed their in-kernel PRNG upon snapshot resume. User space applications can rely on the guest kernel @@ -603,9 +603,6 @@ for randomness. State other than the guest kernel entropy pool, such as unique 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. -On guests that run Linux versions >= 6.8, users can make use of the uevent that -VMGenID driver emits upon resuming from a snapshot, to be notified about -snapshot resume events. ## Vsock device limitation 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 28c073bed22..be969b8c2ac 100644 --- a/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config +++ b/resources/guest_configs/microvm-kernel-ci-aarch64-6.1.config @@ -1943,6 +1943,7 @@ CONFIG_CHARLCD_BL_FLASH=y # CONFIG_UIO is not set # CONFIG_VFIO is not set CONFIG_VIRT_DRIVERS=y +CONFIG_VMGENID=y CONFIG_VIRTIO=y CONFIG_VIRTIO_MENU=y CONFIG_VIRTIO_BALLOON=y diff --git a/resources/patches/vmgenid_dt/0001-virt-vmgenid-change-implementation-to-use-a-platform.patch b/resources/patches/vmgenid_dt/0001-virt-vmgenid-change-implementation-to-use-a-platform.patch new file mode 100644 index 00000000000..688234eadfb --- /dev/null +++ b/resources/patches/vmgenid_dt/0001-virt-vmgenid-change-implementation-to-use-a-platform.patch @@ -0,0 +1,174 @@ +From 1e96eb7dd95b1908428195ef69a30effd562f947 Mon Sep 17 00:00:00 2001 +From: Sudan Landge +Date: Wed, 17 Apr 2024 12:40:42 +0200 +Subject: [PATCH 1/3] virt: vmgenid: change implementation to use a platform + driver + +Re-implement vmgenid as a platform driver in preparation for adding +devicetree bindings support in next commits. + +Signed-off-by: Sudan Landge +Reviewed-by: Alexander Graf +Tested-by: Babis Chalios +[Jason: - Small style cleanups and refactoring.] +Signed-off-by: Jason A. Donenfeld +--- + drivers/virt/vmgenid.c | 99 +++++++++++++++++++++++++++--------------- + 1 file changed, 65 insertions(+), 34 deletions(-) + +diff --git a/drivers/virt/vmgenid.c b/drivers/virt/vmgenid.c +index a1c467a0e9f71..0522107f9beeb 100644 +--- a/drivers/virt/vmgenid.c ++++ b/drivers/virt/vmgenid.c +@@ -7,9 +7,10 @@ + * information to random.c. + */ + ++#include + #include + #include +-#include ++#include + #include + + ACPI_MODULE_NAME("vmgenid"); +@@ -21,19 +22,41 @@ struct vmgenid_state { + u8 this_id[VMGENID_SIZE]; + }; + +-static int vmgenid_add(struct acpi_device *device) ++static void vmgenid_notify(struct device *device) ++{ ++ struct vmgenid_state *state = device->driver_data; ++ u8 old_id[VMGENID_SIZE]; ++ ++ memcpy(old_id, state->this_id, sizeof(old_id)); ++ memcpy(state->this_id, state->next_id, sizeof(state->this_id)); ++ if (!memcmp(old_id, state->this_id, sizeof(old_id))) ++ return; ++ add_vmfork_randomness(state->this_id, sizeof(state->this_id)); ++} ++ ++static void setup_vmgenid_state(struct vmgenid_state *state, void *virt_addr) + { ++ state->next_id = virt_addr; ++ memcpy(state->this_id, state->next_id, sizeof(state->this_id)); ++ add_device_randomness(state->this_id, sizeof(state->this_id)); ++} ++ ++static void vmgenid_acpi_handler(acpi_handle __always_unused handle, ++ u32 __always_unused event, void *dev) ++{ ++ vmgenid_notify(dev); ++} ++ ++static int vmgenid_add_acpi(struct device *dev, struct vmgenid_state *state) ++{ ++ struct acpi_device *device = ACPI_COMPANION(dev); + struct acpi_buffer parsed = { ACPI_ALLOCATE_BUFFER }; +- struct vmgenid_state *state; + union acpi_object *obj; + phys_addr_t phys_addr; + acpi_status status; ++ void *virt_addr; + int ret = 0; + +- state = devm_kmalloc(&device->dev, sizeof(*state), GFP_KERNEL); +- if (!state) +- return -ENOMEM; +- + status = acpi_evaluate_object(device->handle, "ADDR", NULL, &parsed); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating ADDR")); +@@ -49,53 +72,61 @@ static int vmgenid_add(struct acpi_device *device) + + phys_addr = (obj->package.elements[0].integer.value << 0) | + (obj->package.elements[1].integer.value << 32); +- state->next_id = devm_memremap(&device->dev, phys_addr, VMGENID_SIZE, MEMREMAP_WB); +- if (IS_ERR(state->next_id)) { +- ret = PTR_ERR(state->next_id); ++ ++ virt_addr = devm_memremap(&device->dev, phys_addr, VMGENID_SIZE, MEMREMAP_WB); ++ if (IS_ERR(virt_addr)) { ++ ret = PTR_ERR(virt_addr); + goto out; + } ++ setup_vmgenid_state(state, virt_addr); + +- memcpy(state->this_id, state->next_id, sizeof(state->this_id)); +- add_device_randomness(state->this_id, sizeof(state->this_id)); +- +- device->driver_data = state; ++ status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, ++ vmgenid_acpi_handler, dev); ++ if (ACPI_FAILURE(status)) { ++ ret = -ENODEV; ++ goto out; ++ } + ++ dev->driver_data = state; + out: + ACPI_FREE(parsed.pointer); + return ret; + } + +-static void vmgenid_notify(struct acpi_device *device, u32 event) ++static int vmgenid_add(struct platform_device *pdev) + { +- struct vmgenid_state *state = acpi_driver_data(device); +- u8 old_id[VMGENID_SIZE]; ++ struct device *dev = &pdev->dev; ++ struct vmgenid_state *state; ++ int ret; + +- memcpy(old_id, state->this_id, sizeof(old_id)); +- memcpy(state->this_id, state->next_id, sizeof(state->this_id)); +- if (!memcmp(old_id, state->this_id, sizeof(old_id))) +- return; +- add_vmfork_randomness(state->this_id, sizeof(state->this_id)); ++ state = devm_kmalloc(dev, sizeof(*state), GFP_KERNEL); ++ if (!state) ++ return -ENOMEM; ++ ++ ret = vmgenid_add_acpi(dev, state); ++ ++ if (ret < 0) ++ devm_kfree(dev, state); ++ return ret; + } + +-static const struct acpi_device_id vmgenid_ids[] = { ++static const struct acpi_device_id vmgenid_acpi_ids[] = { + { "VMGENCTR", 0 }, + { "VM_GEN_COUNTER", 0 }, + { } + }; +- +-static struct acpi_driver vmgenid_driver = { +- .name = "vmgenid", +- .ids = vmgenid_ids, +- .owner = THIS_MODULE, +- .ops = { +- .add = vmgenid_add, +- .notify = vmgenid_notify +- } ++MODULE_DEVICE_TABLE(acpi, vmgenid_acpi_ids); ++ ++static struct platform_driver vmgenid_plaform_driver = { ++ .probe = vmgenid_add, ++ .driver = { ++ .name = "vmgenid", ++ .acpi_match_table = vmgenid_acpi_ids, ++ }, + }; + +-module_acpi_driver(vmgenid_driver); ++module_platform_driver(vmgenid_plaform_driver) + +-MODULE_DEVICE_TABLE(acpi, vmgenid_ids); + MODULE_DESCRIPTION("Virtual Machine Generation ID"); + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Jason A. Donenfeld "); +-- +2.34.1 + diff --git a/resources/patches/vmgenid_dt/0002-dt-bindings-rng-Add-vmgenid-support.patch b/resources/patches/vmgenid_dt/0002-dt-bindings-rng-Add-vmgenid-support.patch new file mode 100644 index 00000000000..3377db61d6f --- /dev/null +++ b/resources/patches/vmgenid_dt/0002-dt-bindings-rng-Add-vmgenid-support.patch @@ -0,0 +1,135 @@ +From 477bd33715e9d669bc3d5968cd69108241ae099c Mon Sep 17 00:00:00 2001 +From: Sudan Landge +Date: Wed, 17 Apr 2024 12:40:45 +0200 +Subject: [PATCH 2/3] dt-bindings: rng: Add vmgenid support + +Virtual Machine Generation ID driver was introduced in commit +af6b54e2b5ba ("virt: vmgenid: notify RNG of VM fork and supply +generation ID"), as an ACPI only device. + +VMGenID specification http://go.microsoft.com/fwlink/?LinkId=260709 +defines a mechanism for the BIOS/hypervisors to communicate to the +virtual machine that it is executed with a different configuration (e.g. +snapshot execution or creation from a template). The guest operating +system can use the notification for various purposes such as +re-initializing its random number generator etc. + +As per the specs, hypervisor should provide a globally unique +identified, or GUID via ACPI. + +This patch tries to mimic the mechanism to provide the same +functionality which is for a hypervisor/BIOS to notify the virtual +machine when it is executed with a different configuration. + +As part of this support the devicetree bindings requires the hypervisors +or BIOS to provide a memory address which holds the GUID and an IRQ +which is used to notify when there is a change in the GUID. The memory +exposed in the DT should follow the rules defined in the vmgenid spec +mentioned above. + +Reason for this change: Chosing ACPI or devicetree is an intrinsic part +of an hypervisor design. Without going into details of why a hypervisor +would chose DT over ACPI, we would like to highlight that the +hypervisors that have chose devicetree and now want to make use of the +vmgenid functionality cannot do so today because vmgenid is an ACPI only +device. This forces these hypervisors to change their design which +could have undesirable impacts on their use-cases, test-scenarios etc. + +The point of vmgenid is to provide a mechanism to discover a GUID when +the execution state of a virtual machine changes and the simplest way to +do it is pass a memory location and an interrupt via devicetree. It +would complicate things unnecessarily if instead of using devicetree, we +try to implement a new protocol or modify other protocols to somehow +provide the same functionility. + +We believe that adding a devicetree binding for vmgenid is a simpler, +better alternative to provide the same functionality and will allow such +hypervisors as mentioned above to continue using devicetree. + +More references to the vmgenid specs are found below. + +Signed-off-by: Sudan Landge +Reviewed-by: Rob Herring +Reviewed-by: Alexander Graf +Link: https://www.qemu.org/docs/master/specs/vmgenid.html +Link: https://learn.microsoft.com/en-us/windows/win32/hyperv_v2/virtual-machine-generation-identifier +Signed-off-by: Jason A. Donenfeld +--- + .../bindings/rng/microsoft,vmgenid.yaml | 49 +++++++++++++++++++ + MAINTAINERS | 3 +- + 2 files changed, 51 insertions(+), 1 deletion(-) + create mode 100644 Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml + +diff --git a/Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml b/Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml +new file mode 100644 +index 0000000000000..8f20dee93e7ea +--- /dev/null ++++ b/Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml +@@ -0,0 +1,49 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/rng/microsoft,vmgenid.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Virtual Machine Generation ID ++ ++maintainers: ++ - Jason A. Donenfeld ++ ++description: ++ Firmwares or hypervisors can use this devicetree to describe an ++ interrupt and a shared resource to inject a Virtual Machine Generation ID. ++ Virtual Machine Generation ID is a globally unique identifier (GUID) and ++ the devicetree binding follows VMGenID specification defined in ++ http://go.microsoft.com/fwlink/?LinkId=260709. ++ ++properties: ++ compatible: ++ const: microsoft,vmgenid ++ ++ reg: ++ description: ++ Specifies a 16-byte VMGenID in endianness-agnostic hexadecimal format. ++ maxItems: 1 ++ ++ interrupts: ++ description: ++ Interrupt used to notify that a new VMGenID is available. ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ rng@80000000 { ++ compatible = "microsoft,vmgenid"; ++ reg = <0x80000000 0x1000>; ++ interrupts = ; ++ }; ++ ++... +diff --git a/MAINTAINERS b/MAINTAINERS +index 886d3f69ee644..792d1a8b6f422 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17290,8 +17290,9 @@ F: arch/mips/generic/board-ranchu.c + RANDOM NUMBER DRIVER + M: "Theodore Ts'o" + M: Jason A. Donenfeld +-T: git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git + S: Maintained ++T: git https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git ++F: Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml + F: drivers/char/random.c + F: drivers/virt/vmgenid.c + +-- +2.34.1 + diff --git a/resources/patches/vmgenid_dt/0003-virt-vmgenid-add-support-for-devicetree-bindings.patch b/resources/patches/vmgenid_dt/0003-virt-vmgenid-add-support-for-devicetree-bindings.patch new file mode 100644 index 00000000000..af529d537e1 --- /dev/null +++ b/resources/patches/vmgenid_dt/0003-virt-vmgenid-add-support-for-devicetree-bindings.patch @@ -0,0 +1,142 @@ +From 940c65e7be42edba029264cdc61e6b659ace3747 Mon Sep 17 00:00:00 2001 +From: Sudan Landge +Date: Wed, 17 Apr 2024 12:40:46 +0200 +Subject: [PATCH 3/3] virt: vmgenid: add support for devicetree bindings + +Extend the vmgenid platform driver to support devicetree bindings. With +this support, hypervisors can send vmgenid notifications to the virtual +machine without the need to enable ACPI. The bindings are located at: +Documentation/devicetree/bindings/rng/microsoft,vmgenid.yaml + +Since this is no longer ACPI-dependent, remove the dependency from +Kconfig and protect the ACPI code with a single ifdef. + +Signed-off-by: Sudan Landge +Reviewed-by: Alexander Graf +Tested-by: Babis Chalios +[Jason: - Small style cleanups and refactoring. + - Re-work ACPI conditionalization. ] +Signed-off-by: Jason A. Donenfeld +--- + drivers/virt/Kconfig | 1 - + drivers/virt/vmgenid.c | 53 ++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 51 insertions(+), 3 deletions(-) + +diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig +index 87ef258cec648..9f7d64856e096 100644 +--- a/drivers/virt/Kconfig ++++ b/drivers/virt/Kconfig +@@ -16,7 +16,6 @@ if VIRT_DRIVERS + config VMGENID + tristate "Virtual Machine Generation ID driver" + default y +- depends on ACPI + help + Say Y here to use the hypervisor-provided Virtual Machine Generation ID + to reseed the RNG when the VM is cloned. This is highly recommended if +diff --git a/drivers/virt/vmgenid.c b/drivers/virt/vmgenid.c +index 0522107f9beeb..66135eac3abff 100644 +--- a/drivers/virt/vmgenid.c ++++ b/drivers/virt/vmgenid.c +@@ -2,12 +2,13 @@ + /* + * Copyright (C) 2022 Jason A. Donenfeld . All Rights Reserved. + * +- * The "Virtual Machine Generation ID" is exposed via ACPI and changes when a ++ * The "Virtual Machine Generation ID" is exposed via ACPI or DT and changes when a + * virtual machine forks or is cloned. This driver exists for shepherding that + * information to random.c. + */ + + #include ++#include + #include + #include + #include +@@ -41,6 +42,7 @@ static void setup_vmgenid_state(struct vmgenid_state *state, void *virt_addr) + add_device_randomness(state->this_id, sizeof(state->this_id)); + } + ++#ifdef CONFIG_ACPI + static void vmgenid_acpi_handler(acpi_handle __always_unused handle, + u32 __always_unused event, void *dev) + { +@@ -92,6 +94,43 @@ static int vmgenid_add_acpi(struct device *dev, struct vmgenid_state *state) + ACPI_FREE(parsed.pointer); + return ret; + } ++#else ++static int vmgenid_add_acpi(struct device *dev, struct vmgenid_state *state) ++{ ++ return -EINVAL; ++} ++#endif ++ ++static irqreturn_t vmgenid_of_irq_handler(int __always_unused irq, void *dev) ++{ ++ vmgenid_notify(dev); ++ return IRQ_HANDLED; ++} ++ ++static int vmgenid_add_of(struct platform_device *pdev, ++ struct vmgenid_state *state) ++{ ++ void *virt_addr; ++ int ret; ++ ++ virt_addr = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); ++ if (IS_ERR(virt_addr)) ++ return PTR_ERR(virt_addr); ++ ++ setup_vmgenid_state(state, virt_addr); ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_request_irq(&pdev->dev, ret, vmgenid_of_irq_handler, ++ IRQF_SHARED, "vmgenid", &pdev->dev); ++ if (ret < 0) ++ return ret; ++ ++ pdev->dev.driver_data = state; ++ return 0; ++} + + static int vmgenid_add(struct platform_device *pdev) + { +@@ -103,13 +142,22 @@ static int vmgenid_add(struct platform_device *pdev) + if (!state) + return -ENOMEM; + +- ret = vmgenid_add_acpi(dev, state); ++ if (dev->of_node) ++ ret = vmgenid_add_of(pdev, state); ++ else ++ ret = vmgenid_add_acpi(dev, state); + + if (ret < 0) + devm_kfree(dev, state); + return ret; + } + ++static const struct of_device_id vmgenid_of_ids[] = { ++ { .compatible = "microsoft,vmgenid", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, vmgenid_of_ids); ++ + static const struct acpi_device_id vmgenid_acpi_ids[] = { + { "VMGENCTR", 0 }, + { "VM_GEN_COUNTER", 0 }, +@@ -122,6 +170,7 @@ static struct platform_driver vmgenid_plaform_driver = { + .driver = { + .name = "vmgenid", + .acpi_match_table = vmgenid_acpi_ids, ++ .of_match_table = vmgenid_of_ids, + }, + }; + +-- +2.34.1 + diff --git a/resources/rebuild.sh b/resources/rebuild.sh index 5623a425a34..0d253aae59d 100755 --- a/resources/rebuild.sh +++ b/resources/rebuild.sh @@ -184,6 +184,16 @@ function build_linux { format="pe" target="Image" binary_path="arch/arm64/boot/$target" + + # Patch 6.1 kernels on ARM with 6.10 patches for supporting VMGenID + # via DeviceTree bindings. + # TODO: drop this (and remove the patches from the repo) when we switch + # to building kernels from AL tree. + if [[ $KERNEL_VERSION == "6.1" ]]; then + for i in ../patches/vmgenid_dt/* ; do + patch -p1 < $i + done + fi else echo "FATAL: Unsupported architecture!" exit 1 diff --git a/src/vmm/src/arch/aarch64/fdt.rs b/src/vmm/src/arch/aarch64/fdt.rs index 9318928d20c..cbc7884cf98 100644 --- a/src/vmm/src/arch/aarch64/fdt.rs +++ b/src/vmm/src/arch/aarch64/fdt.rs @@ -16,6 +16,7 @@ use super::super::{DeviceType, InitrdConfig}; use super::cache_info::{read_cache_config, CacheEntry}; use super::get_fdt_addr; use super::gic::GICDevice; +use crate::devices::acpi::vmgenid::{VmGenId, VMGENID_MEM_SIZE}; use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap}; // This is a value for uniquely identifying the FDT node declaring the interrupt controller. @@ -25,7 +26,7 @@ const CLOCK_PHANDLE: u32 = 2; // You may be wondering why this big value? // This phandle is used to uniquely identify the FDT nodes containing cache information. Each cpu // can have a variable number of caches, some of these caches may be shared with other cpus. -// So, we start the indexing of the phandles used from a really big number and then substract from +// So, we start the indexing of the phandles used from a really big number and then subtract from // it as we need more and more phandle for each cache representation. const LAST_CACHE_PHANDLE: u32 = 4000; // Read the documentation specified when appending the root node to the FDT. @@ -70,6 +71,7 @@ pub fn create_fdt, gic_device: &GICDevice, + vmgenid: &Option, initrd: &Option, ) -> Result, FdtError> { // Allocate stuff necessary for storing the blob. @@ -97,6 +99,7 @@ pub fn create_fdt Result<(), FdtEr } fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Result<(), FdtError> { - let mem_size = guest_mem.last_addr().raw_value() - super::layout::DRAM_MEM_START + 1; // See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960 // for an explanation of this. - let mem_reg_prop = &[super::layout::DRAM_MEM_START, mem_size]; - let mem = fdt.begin_node("memory")?; + // On ARM we reserve some memory so that it can be utilized for devices like VMGenID to send + // data to kernel drivers. The range of this memory is: + // + // [layout::DRAM_MEM_START, layout::DRAM_MEM_START + layout::SYSTEM_MEM_SIZE) + // + // The reason we do this is that Linux does not allow remapping system memory. However, without + // remap, kernel drivers cannot get virtual addresses to read data from device memory. Leaving + // this memory region out allows Linux kernel modules to remap and thus read this region. + let mem_size = guest_mem.last_addr().raw_value() + - super::layout::DRAM_MEM_START + - super::layout::SYSTEM_MEM_SIZE + + 1; + let mem_reg_prop = &[ + super::layout::DRAM_MEM_START + super::layout::SYSTEM_MEM_SIZE, + mem_size, + ]; + let mem = fdt.begin_node("memory@ram")?; fdt.property_string("device_type", "memory")?; fdt.property_array_u64("reg", mem_reg_prop)?; fdt.end_node(mem)?; @@ -258,6 +275,20 @@ fn create_chosen_node( Ok(()) } +fn create_vmgenid_node(fdt: &mut FdtWriter, vmgenid: &Option) -> Result<(), FdtError> { + if let Some(vmgenid_info) = vmgenid { + let vmgenid = fdt.begin_node("vmgenid")?; + fdt.property_string("compatible", "microsoft,vmgenid")?; + fdt.property_array_u64("reg", &[vmgenid_info.guest_address.0, VMGENID_MEM_SIZE])?; + fdt.property_array_u32( + "interrupts", + &[GIC_FDT_IRQ_TYPE_SPI, vmgenid_info.gsi, IRQ_TYPE_EDGE_RISING], + )?; + fdt.end_node(vmgenid)?; + } + Ok(()) +} + fn create_gic_node(fdt: &mut FdtWriter, gic_device: &GICDevice) -> Result<(), FdtError> { let interrupt = fdt.begin_node("intc")?; fdt.property_string("compatible", gic_device.fdt_compatibility())?; @@ -428,6 +459,7 @@ mod tests { use super::*; use crate::arch::aarch64::gic::create_gic; use crate::arch::aarch64::layout; + use crate::device_manager::resources::ResourceAllocator; use crate::utilities::test_utils::arch_mem; const LEN: u64 = 4096; @@ -492,6 +524,27 @@ mod tests { &dev_info, &gic, &None, + &None, + ) + .unwrap(); + } + + #[test] + fn test_create_fdt_with_vmgenid() { + let mem = arch_mem(layout::FDT_MAX_SIZE + 0x1000); + let mut resource_allocator = ResourceAllocator::new().unwrap(); + let vmgenid = VmGenId::new(&mem, &mut resource_allocator).unwrap(); + let kvm = Kvm::new().unwrap(); + let vm = kvm.create_vm().unwrap(); + let gic = create_gic(&vm, 1, None).unwrap(); + create_fdt( + &mem, + vec![0], + CString::new("console=tty0").unwrap(), + &HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(), + &gic, + &Some(vmgenid), + &None, ) .unwrap(); } @@ -516,6 +569,7 @@ mod tests { &HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(), &gic, &None, + &None, ) .unwrap(); @@ -533,7 +587,7 @@ mod tests { // let mut output = fs::OpenOptions::new() // .write(true) // .create(true) - // .open(path.join(format!("src/aarch64/{}", dtb_path))) + // .open(path.join(format!("src/arch/aarch64/{}", dtb_path))) // .unwrap(); // output.write_all(¤t_dtb_bytes).unwrap(); // } @@ -576,6 +630,7 @@ mod tests { CString::new("console=tty0").unwrap(), &HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(), &gic, + &None, &Some(initrd), ) .unwrap(); @@ -594,7 +649,7 @@ mod tests { // let mut output = fs::OpenOptions::new() // .write(true) // .create(true) - // .open(path.join(format!("src/aarch64/{}", dtb_path))) + // .open(path.join(format!("src/arch/aarch64/{}", dtb_path))) // .unwrap(); // output.write_all(¤t_dtb_bytes).unwrap(); // } diff --git a/src/vmm/src/arch/aarch64/layout.rs b/src/vmm/src/arch/aarch64/layout.rs index 6c4dd7eb6ce..922cfbb66e6 100644 --- a/src/vmm/src/arch/aarch64/layout.rs +++ b/src/vmm/src/arch/aarch64/layout.rs @@ -54,6 +54,14 @@ pub const DRAM_MEM_START: u64 = 0x8000_0000; // 2 GB. /// The maximum RAM size. pub const DRAM_MEM_MAX_SIZE: usize = 0x00FF_8000_0000; // 1024 - 2 = 1022G. +/// Start of RAM on 64 bit ARM. +pub const SYSTEM_MEM_START: u64 = DRAM_MEM_START; + +/// This is used by ACPI device manager for acpi tables or devices like vmgenid +/// In reality, 2MBs is an overkill, but immediately after this we write the kernel +/// image, which needs to be 2MB aligned. +pub const SYSTEM_MEM_SIZE: u64 = 0x20_0000; + /// Kernel command line maximum size. /// As per `arch/arm64/include/uapi/asm/setup.h`. pub const CMDLINE_MAX_SIZE: usize = 2048; diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index 334a8952979..7ed72789325 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -20,6 +20,7 @@ use std::fmt::Debug; pub use self::fdt::DeviceInfoForFDT; use self::gic::GICDevice; use crate::arch::DeviceType; +use crate::devices::acpi::vmgenid::VmGenId; use crate::vstate::memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap}; /// Errors thrown while configuring aarch64 system. @@ -60,6 +61,7 @@ pub fn configure_system, device_info: &HashMap<(DeviceType, String), T, S>, gic_device: &GICDevice, + vmgenid: &Option, initrd: &Option, ) -> Result<(), ConfigurationError> { fdt::create_fdt( @@ -68,6 +70,7 @@ pub fn configure_system u64 { - layout::DRAM_MEM_START + layout::SYSTEM_MEM_START + layout::SYSTEM_MEM_SIZE } /// Returns the memory address where the initrd could be loaded. diff --git a/src/vmm/src/arch/aarch64/output_GICv3.dtb b/src/vmm/src/arch/aarch64/output_GICv3.dtb index c36d6ea2b0d..03fba87f4fe 100644 Binary files a/src/vmm/src/arch/aarch64/output_GICv3.dtb and b/src/vmm/src/arch/aarch64/output_GICv3.dtb differ diff --git a/src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb b/src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb index 38f01c3e3d9..90e4a6cc0e2 100644 Binary files a/src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb and b/src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb differ diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index c29f53fdd61..f5a2f98cb7c 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -12,8 +12,8 @@ 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, ConfigurationError, MMIO_MEM_SIZE, - MMIO_MEM_START, + 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, }; /// Module for x86_64 related functionality. diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 2cf8a66e0bb..27d2ce72dad 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -36,18 +36,14 @@ use crate::cpu_config::templates::{ CpuConfiguration, CustomCpuTemplate, GetCpuTemplate, GetCpuTemplateError, GuestConfigError, KvmCapability, }; -#[cfg(target_arch = "x86_64")] 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::persist::MMIODevManagerConstructorArgs; -#[cfg(target_arch = "x86_64")] use crate::device_manager::persist::{ - ACPIDeviceManagerConstructorArgs, ACPIDeviceManagerRestoreError, + ACPIDeviceManagerConstructorArgs, ACPIDeviceManagerRestoreError, MMIODevManagerConstructorArgs, }; use crate::device_manager::resources::ResourceAllocator; -#[cfg(target_arch = "x86_64")] use crate::devices::acpi::vmgenid::{VmGenId, VmGenIdError}; use crate::devices::legacy::serial::SerialOut; #[cfg(target_arch = "aarch64")] @@ -79,7 +75,6 @@ pub enum StartMicrovmError { /// Unable to attach block device to Vmm: {0} AttachBlockDevice(io::Error), /// Unable to attach the VMGenID device: {0} - #[cfg(target_arch = "x86_64")] AttachVmgenidDevice(kvm_ioctls::Error), /// System configuration error: {0} ConfigureSystem(crate::arch::ConfigurationError), @@ -93,7 +88,6 @@ pub enum StartMicrovmError { #[cfg(target_arch = "x86_64")] CreateLegacyDevice(device_manager::legacy::LegacyDeviceError), /// Error creating VMGenID device: {0} - #[cfg(target_arch = "x86_64")] CreateVMGenID(VmGenIdError), /// Invalid Memory Configuration: {0} GuestMemory(crate::vstate::memory::MemoryError), @@ -175,7 +169,6 @@ fn create_vmm_and_vcpus( let mmio_device_manager = MMIODeviceManager::new(); // Instantiate ACPI device manager. - #[cfg(target_arch = "x86_64")] let acpi_device_manager = ACPIDeviceManager::new(); // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS` @@ -233,7 +226,6 @@ fn create_vmm_and_vcpus( mmio_device_manager, #[cfg(target_arch = "x86_64")] pio_device_manager, - #[cfg(target_arch = "x86_64")] acpi_device_manager, }; @@ -347,7 +339,6 @@ pub fn build_microvm_for_boot( #[cfg(target_arch = "aarch64")] attach_legacy_devices_aarch64(event_manager, &mut vmm, &mut boot_cmdline).map_err(Internal)?; - #[cfg(target_arch = "x86_64")] attach_vmgenid_device(&mut vmm)?; configure_system_for_boot( @@ -449,7 +440,6 @@ pub enum BuildMicrovmFromSnapshotError { /// Failed to apply VMM secccomp filter: {0} SeccompFiltersInternal(#[from] seccompiler::InstallationError), /// Failed to restore ACPI device manager: {0} - #[cfg(target_arch = "x86_64")] ACPIDeviManager(#[from] ACPIDeviceManagerRestoreError), /// VMGenID update failed: {0} VMGenIDUpdate(std::io::Error), @@ -532,7 +522,6 @@ pub fn build_microvm_from_snapshot( .map_err(MicrovmStateError::RestoreDevices)?; vmm.emulate_serial_init()?; - #[cfg(target_arch = "x86_64")] { let acpi_ctor_args = ACPIDeviceManagerConstructorArgs { mem: &guest_memory, @@ -859,6 +848,7 @@ pub fn configure_system_for_boot( vcpu_mpidr, vmm.mmio_device_manager.get_device_info(), vmm.vm.get_irqchip(), + &vmm.acpi_device_manager.vmgenid, initrd, ) .map_err(ConfigureSystem)?; @@ -908,7 +898,6 @@ pub(crate) fn attach_boot_timer_device( Ok(()) } -#[cfg(target_arch = "x86_64")] fn attach_vmgenid_device(vmm: &mut Vmm) -> Result<(), StartMicrovmError> { let vmgenid = VmGenId::new(&vmm.guest_memory, &mut vmm.resource_allocator) .map_err(StartMicrovmError::CreateVMGenID)?; @@ -1117,7 +1106,6 @@ pub mod tests { let mut vm = Vm::new(vec![]).unwrap(); vm.memory_init(&guest_memory, false).unwrap(); let mmio_device_manager = MMIODeviceManager::new(); - #[cfg(target_arch = "x86_64")] let acpi_device_manager = ACPIDeviceManager::new(); #[cfg(target_arch = "x86_64")] let pio_device_manager = PortIODeviceManager::new( @@ -1158,7 +1146,6 @@ pub mod tests { mmio_device_manager, #[cfg(target_arch = "x86_64")] pio_device_manager, - #[cfg(target_arch = "x86_64")] acpi_device_manager, } } diff --git a/src/vmm/src/device_manager/mod.rs b/src/vmm/src/device_manager/mod.rs index 24b9c373bc1..bc16604b645 100644 --- a/src/vmm/src/device_manager/mod.rs +++ b/src/vmm/src/device_manager/mod.rs @@ -6,7 +6,6 @@ // found in the THIRD-PARTY file. /// ACPI device manager. -#[cfg(target_arch = "x86_64")] pub mod acpi; /// Legacy Device Manager. pub mod legacy; diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index 5b72cff9a24..7a51bf790e9 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -12,13 +12,11 @@ use log::{error, warn}; use serde::{Deserialize, Serialize}; use vm_allocator::AllocPolicy; -#[cfg(target_arch = "x86_64")] use super::acpi::ACPIDeviceManager; use super::mmio::*; use super::resources::ResourceAllocator; #[cfg(target_arch = "aarch64")] use crate::arch::DeviceType; -#[cfg(target_arch = "x86_64")] use crate::devices::acpi::vmgenid::{VMGenIDState, VMGenIdConstructorArgs, VmGenId, VmGenIdError}; use crate::devices::virtio::balloon::persist::{BalloonConstructorArgs, BalloonState}; use crate::devices::virtio::balloon::{Balloon, BalloonError}; @@ -230,20 +228,17 @@ impl fmt::Debug for MMIODevManagerConstructorArgs<'_> { } } -#[cfg(target_arch = "x86_64")] #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct ACPIDeviceManagerState { vmgenid: Option, } -#[cfg(target_arch = "x86_64")] pub struct ACPIDeviceManagerConstructorArgs<'a> { pub mem: &'a GuestMemoryMmap, pub resource_allocator: &'a mut ResourceAllocator, pub vm: &'a VmFd, } -#[cfg(target_arch = "x86_64")] #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum ACPIDeviceManagerRestoreError { /// Could not register device: {0} @@ -252,7 +247,6 @@ pub enum ACPIDeviceManagerRestoreError { VMGenID(#[from] VmGenIdError), } -#[cfg(target_arch = "x86_64")] impl<'a> Persist<'a> for ACPIDeviceManager { type State = ACPIDeviceManagerState; type ConstructorArgs = ACPIDeviceManagerConstructorArgs<'a>; diff --git a/src/vmm/src/device_manager/resources.rs b/src/vmm/src/device_manager/resources.rs index 851893bd4ca..821148794ec 100644 --- a/src/vmm/src/device_manager/resources.rs +++ b/src/vmm/src/device_manager/resources.rs @@ -20,7 +20,6 @@ pub struct ResourceAllocator { // Allocator for memory in the MMIO address space mmio_memory: AddressAllocator, // Memory allocator for system data - #[cfg(target_arch = "x86_64")] system_memory: AddressAllocator, } @@ -30,7 +29,6 @@ impl ResourceAllocator { Ok(Self { gsi_allocator: IdAllocator::new(arch::IRQ_BASE, arch::IRQ_MAX)?, mmio_memory: AddressAllocator::new(arch::MMIO_MEM_START, arch::MMIO_MEM_SIZE)?, - #[cfg(target_arch = "x86_64")] system_memory: AddressAllocator::new(arch::SYSTEM_MEM_START, arch::SYSTEM_MEM_SIZE)?, }) } @@ -86,7 +84,6 @@ impl ResourceAllocator { /// * `size` - The size in bytes of the memory to allocate /// * `alignment` - The alignment of the address of the first byte /// * `policy` - A [`vm_allocator::AllocPolicy`] variant for determining the allocation policy - #[cfg(target_arch = "x86_64")] pub fn allocate_system_memory( &mut self, size: u64, diff --git a/src/vmm/src/devices/acpi/vmgenid.rs b/src/vmm/src/devices/acpi/vmgenid.rs index b60343e473b..47fb456e7ae 100644 --- a/src/vmm/src/devices/acpi/vmgenid.rs +++ b/src/vmm/src/devices/acpi/vmgenid.rs @@ -15,6 +15,9 @@ use crate::device_manager::resources::ResourceAllocator; use crate::snapshot::Persist; use crate::vstate::memory::{Bytes, GuestMemoryMmap}; +/// Bytes of memory we allocate for VMGenID device +pub const VMGENID_MEM_SIZE: u64 = 16; + /// Virtual Machine Generation ID device /// /// VMGenID is an emulated device which exposes to the guest a 128-bit cryptographically random @@ -86,8 +89,9 @@ impl VmGenId { resource_allocator: &mut ResourceAllocator, ) -> Result { let gsi = resource_allocator.allocate_gsi(1)?; + // The generation ID needs to live in an 8-byte aligned buffer let addr = resource_allocator.allocate_system_memory( - 4096, + VMGENID_MEM_SIZE, 8, vm_allocator::AllocPolicy::LastMatch, )?; @@ -149,7 +153,7 @@ impl<'a> Persist<'a> for VmGenId { state: &Self::State, ) -> std::result::Result { constructor_args.resource_allocator.allocate_system_memory( - 4096, + VMGENID_MEM_SIZE, 8, vm_allocator::AllocPolicy::ExactMatch(state.addr), )?; diff --git a/src/vmm/src/devices/mod.rs b/src/vmm/src/devices/mod.rs index 393b4234515..0ca445b6f82 100644 --- a/src/vmm/src/devices/mod.rs +++ b/src/vmm/src/devices/mod.rs @@ -9,7 +9,6 @@ use std::io; -#[cfg(target_arch = "x86_64")] pub mod acpi; pub mod bus; pub mod legacy; diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index 1228ef8e7bf..ee27194e41b 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -117,10 +117,8 @@ use std::sync::mpsc::RecvTimeoutError; use std::sync::{Arc, Barrier, Mutex}; use std::time::Duration; -#[cfg(target_arch = "x86_64")] use device_manager::acpi::ACPIDeviceManager; use device_manager::resources::ResourceAllocator; -#[cfg(target_arch = "x86_64")] use devices::acpi::vmgenid::VmGenIdError; use event_manager::{EventManager as BaseEventManager, EventOps, Events, MutEventSubscriber}; use seccompiler::BpfProgram; @@ -261,7 +259,6 @@ pub enum VmmError { /// Error thrown by observer object on Vmm teardown: {0} VmmObserverTeardown(utils::errno::Error), /// VMGenID error: {0} - #[cfg(target_arch = "x86_64")] VMGenID(#[from] VmGenIdError), } @@ -318,13 +315,12 @@ pub struct Vmm { // Used by Vcpus and devices to initiate teardown; Vmm should never write here. vcpus_exit_evt: EventFd, - // Allocator for guest resrouces + // Allocator for guest resources resource_allocator: ResourceAllocator, // Guest VM devices. mmio_device_manager: MMIODeviceManager, #[cfg(target_arch = "x86_64")] pio_device_manager: PortIODeviceManager, - #[cfg(target_arch = "x86_64")] acpi_device_manager: ACPIDeviceManager, } @@ -530,7 +526,6 @@ impl Vmm { let device_states = self.mmio_device_manager.save(); let memory_state = self.guest_memory().describe(); - #[cfg(target_arch = "x86_64")] let acpi_dev_state = self.acpi_device_manager.save(); Ok(MicrovmState { @@ -539,7 +534,6 @@ impl Vmm { vm_state, vcpu_states, device_states, - #[cfg(target_arch = "x86_64")] acpi_dev_state, }) } diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index b8dea588459..14e051e19ec 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -26,9 +26,7 @@ use crate::cpu_config::templates::StaticCpuTemplate; 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::device_manager::persist::ACPIDeviceManagerState; -use crate::device_manager::persist::{DevicePersistError, DeviceStates}; +use crate::device_manager::persist::{ACPIDeviceManagerState, DevicePersistError, DeviceStates}; use crate::logger::{info, warn}; use crate::resources::VmResources; use crate::snapshot::Snapshot; @@ -86,7 +84,6 @@ pub struct MicrovmState { /// Device states. pub device_states: DeviceStates, /// ACPI devices state. - #[cfg(target_arch = "x86_64")] pub acpi_dev_state: ACPIDeviceManagerState, } @@ -728,7 +725,6 @@ mod tests { vm_state: vmm.vm.save_state(&mpidrs).unwrap(), #[cfg(target_arch = "x86_64")] vm_state: vmm.vm.save_state().unwrap(), - #[cfg(target_arch = "x86_64")] acpi_dev_state: vmm.acpi_device_manager.save(), }; diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py index 809fbea097c..998d5d027af 100644 --- a/tests/integration_tests/functional/test_snapshot_basic.py +++ b/tests/integration_tests/functional/test_snapshot_basic.py @@ -14,7 +14,6 @@ import host_tools.drive as drive_tools 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, @@ -547,9 +546,6 @@ def test_vmgenid(guest_kernel_linux_6_1, rootfs, microvm_factory, snapshot_type) """ Test VMGenID device upon snapshot resume """ - if global_props.cpu_architecture != "x86_64": - pytest.skip("At the moment we only support VMGenID on x86_64") - base_vm = microvm_factory.build(guest_kernel_linux_6_1, rootfs) base_vm.spawn() base_vm.basic_config(track_dirty_pages=True)