From: Alexander Graf <graf@amazon.com>
To: <qemu-devel@nongnu.org>
Cc: <qemu-arm@nongnu.org>, Peter Maydell <peter.maydell@linaro.org>,
"Thomas Huth" <thuth@redhat.com>, <alex.bennee@linaro.org>,
<philmd@linaro.org>, <berrange@redhat.com>,
<marcandre.lureau@redhat.com>, Cornelia Huck <cohuck@redhat.com>,
<mst@redhat.com>, Dorjoy Chowdhury <dorjoychy111@gmail.com>,
Pierrick Bouvier <pierrick.bouvier@linaro.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Tyler Fanelli <tfanelli@redhat.com>, <mknaust@amazon.com>,
<nh-open-source@amazon.com>
Subject: [PATCH 07/10] hw/nitro: Add nitro machine
Date: Wed, 18 Feb 2026 01:51:47 +0000 [thread overview]
Message-ID: <20260218015151.4052-8-graf@amazon.com> (raw)
In-Reply-To: <20260218015151.4052-1-graf@amazon.com>
Add a machine model to spawn a Nitro Enclave. Unlike the existing -M
nitro-enclave, this machine model works exclusively with the -accel
nitro accelerator to drive real Nitro Enclave creation. It supports
memory allocation, number of CPU selection, both x86_64 as well as
aarch64, implements the Enclave heartbeat logic and debug serial
console.
To use it, create an EIF file and run
$ qemu-system-x86_64 -accel nitro,debug-mode=on -M nitro -nographic \
-kernel test.eif
or
$ qemu-system-aarch64 -accel nitro,debug-mode=on -M nitro -nographic \
-kernel test.eif
Signed-off-by: Alexander Graf <graf@amazon.com>
---
hw/nitro/Kconfig | 7 ++
hw/nitro/machine.c | 180 +++++++++++++++++++++++++++++++++++++
hw/nitro/meson.build | 1 +
include/hw/nitro/machine.h | 20 +++++
4 files changed, 208 insertions(+)
create mode 100644 hw/nitro/machine.c
create mode 100644 include/hw/nitro/machine.h
diff --git a/hw/nitro/Kconfig b/hw/nitro/Kconfig
index 6fe050d35d..910068c23c 100644
--- a/hw/nitro/Kconfig
+++ b/hw/nitro/Kconfig
@@ -5,3 +5,10 @@ config NITRO_SERIAL_VSOCK
config NITRO_HEARTBEAT
bool
depends on NITRO
+
+config NITRO_MACHINE
+ bool
+ default y
+ depends on NITRO
+ select NITRO_HEARTBEAT
+ select NITRO_SERIAL_VSOCK
diff --git a/hw/nitro/machine.c b/hw/nitro/machine.c
new file mode 100644
index 0000000000..197adfbdb5
--- /dev/null
+++ b/hw/nitro/machine.c
@@ -0,0 +1,180 @@
+/*
+ * Nitro Enclaves (accel) machine
+ *
+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors:
+ * Alexander Graf <graf@amazon.com>
+ *
+ * Nitro Enclaves machine model for -accel nitro. This machine behaves
+ * like the nitro-enclave machine, but uses the real Nitro Enclaves
+ * backend to launch the virtual machine. It requires use of the -accel
+ * nitro.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "chardev/char.h"
+#include "hw/core/boards.h"
+#include "hw/core/cpu.h"
+#include "hw/core/sysbus.h"
+#include "hw/core/qdev-properties-system.h"
+#include "hw/nitro/heartbeat.h"
+#include "hw/nitro/machine.h"
+#include "hw/nitro/serial-vsock.h"
+#include "system/address-spaces.h"
+#include "system/hostmem.h"
+#include "system/system.h"
+#include "system/nitro-accel.h"
+#include "qemu/accel.h"
+#include "hw/arm/machines-qom.h"
+
+#define EIF_LOAD_ADDR (8 * 1024 * 1024)
+
+static void nitro_create_cpu(const char *cpu_type, int index)
+{
+ Object *obj = object_new(cpu_type);
+
+ /* x86 CPUs require an apic-id before realize */
+ if (object_property_find(obj, "apic-id")) {
+ object_property_set_int(obj, "apic-id", index, &error_fatal);
+ }
+
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
+}
+
+static void nitro_machine_init(MachineState *machine)
+{
+ const char *eif_path = machine->kernel_filename;
+ const char *cpu_type = machine->cpu_type;
+ g_autofree char *eif_data = NULL;
+ gsize eif_size;
+ int i;
+
+ if (!nitro_enabled()) {
+ error_report("The 'nitro' machine requires -accel nitro");
+ exit(1);
+ }
+
+ if (!cpu_type) {
+ ObjectClass *oc = cpu_class_by_name(target_cpu_type(), "host");
+
+ if (!oc) {
+ error_report("nitro: no 'host' CPU available");
+ exit(1);
+ }
+ cpu_type = object_class_get_name(oc);
+ }
+
+ if (!eif_path) {
+ error_report("nitro: -kernel <eif-file> is required");
+ exit(1);
+ }
+
+ /* Expose memory as normal QEMU RAM. Needs to be huge page backed. */
+ memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+
+ /*
+ * Load EIF (-kernel) as raw blob at the EIF_LOAD_ADDR into guest RAM.
+ * The Nitro Hypervisor will extract its contents and bootstrap the
+ * Enclave from it.
+ */
+ if (!g_file_get_contents(eif_path, &eif_data, &eif_size, NULL)) {
+ error_report("nitro: failed to read EIF '%s'", eif_path);
+ exit(1);
+ }
+ address_space_write(&address_space_memory, EIF_LOAD_ADDR,
+ MEMTXATTRS_UNSPECIFIED, eif_data, eif_size);
+
+ /* Nitro Enclaves require a heartbeat device. Provide one. */
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(qdev_new(TYPE_NITRO_HEARTBEAT)),
+ &error_fatal);
+
+ /*
+ * In debug mode, Nitro Enclaves expose the guest's serial output via
+ * vsock. When the accel is in debug mode, wire the vsock serial to
+ * the machine's serial port so that -nographic automatically works
+ */
+ if (object_property_get_bool(OBJECT(current_accel()), "debug-mode", NULL)) {
+ Chardev *chr = serial_hd(0);
+
+ if (chr) {
+ DeviceState *dev = qdev_new(TYPE_NITRO_SERIAL_VSOCK);
+
+ qdev_prop_set_chr(dev, "chardev", chr);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+ }
+ }
+
+ /*
+ * Spawn vCPUs. While the real Nitro Enclaves CPUs are owned by the
+ * underlying hypervisor, we still want to maintain a local view of
+ * them to trigger VM creation when vCPU 0 starts and to give us an
+ * object to interact with.
+ */
+ for (i = 0; i < machine->smp.cpus; i++) {
+ nitro_create_cpu(cpu_type, i);
+ }
+}
+
+static bool nitro_create_memfd_backend(MachineState *ms, const char *path,
+ Error **errp)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+ Object *root = object_get_objects_root();
+ Object *obj;
+ bool r = false;
+
+ obj = object_new(TYPE_MEMORY_BACKEND_MEMFD);
+
+ /* Nitro Enclaves require huge page backing */
+ if (!object_property_set_int(obj, "size", ms->ram_size, errp) ||
+ !object_property_set_bool(obj, "hugetlb", true, errp)) {
+ goto out;
+ }
+
+ object_property_add_child(root, mc->default_ram_id, obj);
+
+ if (!user_creatable_complete(USER_CREATABLE(obj), errp)) {
+ goto out;
+ }
+ r = object_property_set_link(OBJECT(ms), "memory-backend", obj, errp);
+
+out:
+ object_unref(obj);
+ return r;
+}
+
+static void nitro_machine_class_init(ObjectClass *oc, const void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Nitro Enclave";
+ mc->init = nitro_machine_init;
+ mc->create_default_memdev = nitro_create_memfd_backend;
+ mc->default_ram_id = "ram";
+ mc->max_cpus = 4096;
+}
+
+static const TypeInfo nitro_machine_info = {
+ .name = TYPE_NITRO_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(NitroMachineState),
+ .class_init = nitro_machine_class_init,
+ .interfaces = (const InterfaceInfo[]) {
+ /* x86_64 and aarch64 only */
+ { TYPE_TARGET_AARCH64_MACHINE },
+ { }
+ },
+};
+
+static void nitro_machine_register(void)
+{
+ type_register_static(&nitro_machine_info);
+}
+
+type_init(nitro_machine_register);
diff --git a/hw/nitro/meson.build b/hw/nitro/meson.build
index b921da2b97..813f5a9c87 100644
--- a/hw/nitro/meson.build
+++ b/hw/nitro/meson.build
@@ -1,2 +1,3 @@
system_ss.add(when: 'CONFIG_NITRO_SERIAL_VSOCK', if_true: files('serial-vsock.c'))
system_ss.add(when: 'CONFIG_NITRO_HEARTBEAT', if_true: files('heartbeat.c'))
+system_ss.add(when: 'CONFIG_NITRO_MACHINE', if_true: files('machine.c'))
diff --git a/include/hw/nitro/machine.h b/include/hw/nitro/machine.h
new file mode 100644
index 0000000000..d78ba7d6dc
--- /dev/null
+++ b/include/hw/nitro/machine.h
@@ -0,0 +1,20 @@
+/*
+ * Nitro Enclaves (accel) machine
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_NITRO_MACHINE_H
+#define HW_NITRO_MACHINE_H
+
+#include "hw/core/boards.h"
+#include "qom/object.h"
+
+#define TYPE_NITRO_MACHINE MACHINE_TYPE_NAME("nitro")
+OBJECT_DECLARE_SIMPLE_TYPE(NitroMachineState, NITRO_MACHINE)
+
+struct NitroMachineState {
+ MachineState parent;
+};
+
+#endif /* HW_NITRO_MACHINE_H */
--
2.47.1
Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
next prev parent reply other threads:[~2026-02-18 1:53 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-18 1:51 [PATCH 00/10] Native Nitro Enclaves support Alexander Graf
2026-02-18 1:51 ` [PATCH 01/10] scripts/update-linux-headers: Add Nitro Enclaves header Alexander Graf
2026-02-18 1:51 ` [PATCH 02/10] linux-headers: Add nitro_enclaves.h Alexander Graf
2026-02-18 1:51 ` [PATCH 03/10] accel: Add Nitro Enclaves accelerator Alexander Graf
2026-02-24 10:22 ` Paolo Bonzini
2026-02-24 23:16 ` Alexander Graf
2026-02-18 1:51 ` [PATCH 04/10] hw/nitro/nitro-serial-vsock: Nitro Enclaves vsock console Alexander Graf
2026-02-18 1:51 ` [PATCH 05/10] hw/nitro: Introduce Nitro Enclave Heartbeat device Alexander Graf
2026-02-18 1:51 ` [PATCH 06/10] target/arm/cpu64: Allow -host for nitro Alexander Graf
2026-02-18 1:51 ` Alexander Graf [this message]
2026-02-18 3:27 ` [PATCH 07/10] hw/nitro: Add nitro machine Mohamed Mediouni
2026-02-18 9:20 ` Alexander Graf
2026-02-20 14:59 ` Michael S. Tsirkin
2026-02-20 15:07 ` Alexander Graf
2026-02-18 1:51 ` [PATCH 08/10] hw/core/eif: Move definitions to header Alexander Graf
2026-02-18 15:12 ` Dorjoy Chowdhury
2026-02-18 1:51 ` [PATCH 09/10] hw/nitro: Enable direct kernel boot Alexander Graf
2026-02-18 1:51 ` [PATCH 10/10] docs: Add Nitro Enclaves documentation Alexander Graf
2026-02-24 10:26 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260218015151.4052-8-graf@amazon.com \
--to=graf@amazon.com \
--cc=alex.bennee@linaro.org \
--cc=berrange@redhat.com \
--cc=cohuck@redhat.com \
--cc=dorjoychy111@gmail.com \
--cc=marcandre.lureau@redhat.com \
--cc=mknaust@amazon.com \
--cc=mst@redhat.com \
--cc=nh-open-source@amazon.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=pierrick.bouvier@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=tfanelli@redhat.com \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.