{"id":2197509,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2197509/?format=json","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.0/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260218015151.4052-4-graf@amazon.com>","date":"2026-02-18T01:51:43","name":"[03/10] accel: Add Nitro Enclaves accelerator","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"3f6943e3e502d2463dd7ccb7c13dd750a030a550","submitter":{"id":76572,"url":"http://patchwork.ozlabs.org/api/1.0/people/76572/?format=json","name":"Alexander Graf","email":"graf@amazon.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260218015151.4052-4-graf@amazon.com/mbox/","series":[{"id":492503,"url":"http://patchwork.ozlabs.org/api/1.0/series/492503/?format=json","date":"2026-02-18T01:51:40","name":"Native Nitro Enclaves support","version":1,"mbox":"http://patchwork.ozlabs.org/series/492503/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2197509/checks/","tags":{},"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=amazon.com header.i=@amazon.com header.a=rsa-sha256\n header.s=amazoncorp2 header.b=AWGLGh93;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fG01D0W84z1xwC\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 12:54:08 +1100 (AEDT)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1vsWjy-0007CQ-02; Tue, 17 Feb 2026 20:52:34 -0500","from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <prvs=502105d20=graf@amazon.de>)\n id 1vsWjv-0007Bz-DA; Tue, 17 Feb 2026 20:52:31 -0500","from pdx-out-005.esa.us-west-2.outbound.mail-perimeter.amazon.com\n ([52.13.214.179])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <prvs=502105d20=graf@amazon.de>)\n id 1vsWjs-0005F9-4A; Tue, 17 Feb 2026 20:52:31 -0500","from ip-10-5-12-219.us-west-2.compute.internal (HELO\n smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.12.219])\n by internal-pdx-out-005.esa.us-west-2.outbound.mail-perimeter.amazon.com with\n ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2026 01:52:26 +0000","from EX19MTAUWC001.ant.amazon.com [205.251.233.105:6549]\n by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.55.107:2525]\n with esmtp (Farcaster)\n id 5b767f59-cd1d-4935-9b4e-fd445c0e6f0b;\n Wed, 18 Feb 2026 01:52:25 +0000 (UTC)","from EX19D020UWC004.ant.amazon.com (10.13.138.149) by\n EX19MTAUWC001.ant.amazon.com (10.250.64.174) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.35;\n Wed, 18 Feb 2026 01:52:25 +0000","from ip-10-253-83-51.amazon.com (172.19.99.218) by\n EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.35;\n Wed, 18 Feb 2026 01:52:22 +0000"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2;\n t=1771379548; x=1802915548;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=QNgMYQG55uLndwuZXf+YFr1Fjz5BDXtiyzmiHn4qOg4=;\n b=AWGLGh93EZAcbI71/YqFlkb1dmvjde+4ByKJ019GVaIJVaIt1JjsOBVF\n WewjQaSeh8tJM8RQESgfnNpJCIzPnI25BZcpVP0vYfgT35upShChhvryt\n PGQNKzbVOgTC/njh6hc/sVVOgaxSK/Spa9kSJudQwqOouL7XxFCFpr/ud\n 1X417bRHGhBQPmLSXk+udyMJht9SSquFD0ZyafMGtMpSkgLC9hqnfi1qx\n J+gUCRyASLUj1xXqOFnXVirRMY4Q6hNyDqmNBioyDWfPjq/Qv/OMVAPlE\n 1OVoqkXxIdAshJYnThgqst91c12N2o9is5/1icdedBYjeESm257YQiaaB A==;","X-CSE-ConnectionGUID":"TexyZQ3/Qwmk3xMtDLGaJg==","X-CSE-MsgGUID":"SZJ2Hq4CSYufZky05Y/AbA==","X-IronPort-AV":"E=Sophos;i=\"6.21,297,1763424000\"; d=\"scan'208\";a=\"13261392\"","X-Farcaster-Flow-ID":"5b767f59-cd1d-4935-9b4e-fd445c0e6f0b","From":"Alexander Graf <graf@amazon.com>","To":"<qemu-devel@nongnu.org>","CC":"<qemu-arm@nongnu.org>, Peter Maydell <peter.maydell@linaro.org>, \"Thomas\n Huth\" <thuth@redhat.com>, <alex.bennee@linaro.org>, <philmd@linaro.org>,\n <berrange@redhat.com>, <marcandre.lureau@redhat.com>, Cornelia Huck\n <cohuck@redhat.com>, <mst@redhat.com>, Dorjoy Chowdhury\n <dorjoychy111@gmail.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>,\n Paolo Bonzini <pbonzini@redhat.com>, Tyler Fanelli <tfanelli@redhat.com>,\n <mknaust@amazon.com>, <nh-open-source@amazon.com>","Subject":"[PATCH 03/10] accel: Add Nitro Enclaves accelerator","Date":"Wed, 18 Feb 2026 01:51:43 +0000","Message-ID":"<20260218015151.4052-4-graf@amazon.com>","X-Mailer":"git-send-email 2.47.1","In-Reply-To":"<20260218015151.4052-1-graf@amazon.com>","References":"<20260218015151.4052-1-graf@amazon.com>","MIME-Version":"1.0","X-Originating-IP":"[172.19.99.218]","X-ClientProxiedBy":"EX19D043UWC001.ant.amazon.com (10.13.139.202) To\n EX19D020UWC004.ant.amazon.com (10.13.138.149)","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Received-SPF":"pass client-ip=52.13.214.179;\n envelope-from=prvs=502105d20=graf@amazon.de;\n helo=pdx-out-005.esa.us-west-2.outbound.mail-perimeter.amazon.com","X-Spam_score_int":"-19","X-Spam_score":"-2.0","X-Spam_bar":"--","X-Spam_report":"(-2.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.043,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\n HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_NONE=0.001, T_SPF_PERMERROR=0.01,\n UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"Nitro Enclaves are a confidential compute technology which\nallows a parent instance to carve out resources from itself\nand spawn a confidential sibling VM next to itself. Similar\nto other confidential compute solutions, this sibling is\ncontrolled by an underlying vmm, but still has a higher level\nvmm (QEMU) to implement some of its I/O functionality and\nlifecycle.\n\nAdd an accelerator to drive this interface. In combination with\nfollow-on patches to enhance the Nitro Enclaves machine model, this\nwill allow users to run a Nitro Enclave using QEMU.\n\nSigned-off-by: Alexander Graf <graf@amazon.com>\n---\n MAINTAINERS                   |   6 +\n accel/Kconfig                 |   3 +\n accel/meson.build             |   1 +\n accel/nitro/meson.build       |   3 +\n accel/nitro/nitro-accel.c     | 333 ++++++++++++++++++++++++++++++++++\n accel/nitro/trace-events      |   6 +\n accel/nitro/trace.h           |   2 +\n accel/stubs/meson.build       |   1 +\n accel/stubs/nitro-stub.c      |  11 ++\n include/system/hw_accel.h     |   1 +\n include/system/nitro-accel.h  |  25 +++\n meson.build                   |  11 ++\n meson_options.txt             |   2 +\n qemu-options.hx               |   8 +-\n scripts/meson-buildoptions.sh |   3 +\n 15 files changed, 412 insertions(+), 4 deletions(-)\n create mode 100644 accel/nitro/meson.build\n create mode 100644 accel/nitro/nitro-accel.c\n create mode 100644 accel/nitro/trace-events\n create mode 100644 accel/nitro/trace.h\n create mode 100644 accel/stubs/nitro-stub.c\n create mode 100644 include/system/nitro-accel.h","diff":"diff --git a/MAINTAINERS b/MAINTAINERS\nindex d3aa6d6732..3d002143ae 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -583,6 +583,12 @@ F: include/system/mshv.h\n F: include/hw/hyperv/hvgdk*.h\n F: include/hw/hyperv/hvhdk*.h\n \n+Nitro Enclaves (native)\n+M: Alexander Graf <graf@amazon.com>\n+S: Maintained\n+F: accel/nitro/\n+F: include/system/nitro-accel.h\n+\n X86 MSHV CPUs\n M: Magnus Kulke <magnus.kulke@linux.microsoft.com>\n R: Wei Liu <wei.liu@kernel.org>\ndiff --git a/accel/Kconfig b/accel/Kconfig\nindex a60f114923..6d052875ee 100644\n--- a/accel/Kconfig\n+++ b/accel/Kconfig\n@@ -16,6 +16,9 @@ config KVM\n config MSHV\n     bool\n \n+config NITRO\n+    bool\n+\n config XEN\n     bool\n     select FSDEV_9P if VIRTFS\ndiff --git a/accel/meson.build b/accel/meson.build\nindex 289b7420ff..7da12b9741 100644\n--- a/accel/meson.build\n+++ b/accel/meson.build\n@@ -12,6 +12,7 @@ if have_system\n   subdir('xen')\n   subdir('stubs')\n   subdir('mshv')\n+  subdir('nitro')\n endif\n \n # qtest\ndiff --git a/accel/nitro/meson.build b/accel/nitro/meson.build\nnew file mode 100644\nindex 0000000000..e01c1bab96\n--- /dev/null\n+++ b/accel/nitro/meson.build\n@@ -0,0 +1,3 @@\n+nitro_ss = ss.source_set()\n+nitro_ss.add(files('nitro-accel.c'))\n+system_ss.add_all(when: 'CONFIG_NITRO', if_true: nitro_ss)\ndiff --git a/accel/nitro/nitro-accel.c b/accel/nitro/nitro-accel.c\nnew file mode 100644\nindex 0000000000..bea76fcd0b\n--- /dev/null\n+++ b/accel/nitro/nitro-accel.c\n@@ -0,0 +1,333 @@\n+/*\n+ * Nitro Enclaves accelerator\n+ *\n+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n+ *\n+ * Authors:\n+ *   Alexander Graf <graf@amazon.com>\n+ *\n+ * Nitro Enclaves are a confidential compute technology which\n+ * allows a parent instance to carve out resources from itself\n+ * and spawn a confidential sibling VM next to itself. Similar\n+ * to other confidential compute solutions, this sibling is\n+ * controlled by an underlying vmm, but still has a higher level\n+ * vmm (QEMU) to implement some of its I/O functionality and\n+ * lifecycle.\n+ *\n+ * This accelerator drives /dev/nitro_enclaves to spawn a Nitro\n+ * Enclave. It works in tandem with the nitro_enclaves machine\n+ * which ensures the correct backend devices are available and\n+ * that the initial seed (an EIF file) is loaded at the correct\n+ * offset in memory.\n+ *\n+ * The accel starts the enclave on first vCPU 0 main loop entry,\n+ * to ensure that all device setup is finished and that we have\n+ * a working vCPU loop.\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qapi/error.h\"\n+#include \"qapi/visitor.h\"\n+#include \"qemu/module.h\"\n+#include \"qemu/rcu.h\"\n+#include \"qemu/accel.h\"\n+#include \"qemu/guest-random.h\"\n+#include \"qemu/main-loop.h\"\n+#include \"accel/accel-ops.h\"\n+#include \"accel/accel-cpu-ops.h\"\n+#include \"system/cpus.h\"\n+#include \"hw/core/cpu.h\"\n+#include \"hw/core/boards.h\"\n+#include \"hw/core/sysbus.h\"\n+#include \"system/ramblock.h\"\n+#include \"system/nitro-accel.h\"\n+#include \"trace.h\"\n+\n+#include <sys/ioctl.h>\n+#include \"standard-headers/linux/nitro_enclaves.h\"\n+\n+bool nitro_allowed;\n+\n+typedef struct NitroAccelState {\n+    AccelState parent_obj;\n+\n+    int ne_fd;\n+    int enclave_fd;\n+    uint64_t slot_uid;\n+    uint64_t enclave_cid;\n+    bool debug_mode;\n+} NitroAccelState;\n+\n+static int nitro_init_machine(AccelState *as, MachineState *ms)\n+{\n+    NitroAccelState *s = NITRO_ACCEL(as);\n+    uint64_t slot_uid = 0;\n+    int ret;\n+\n+    s->ne_fd = open(\"/dev/nitro_enclaves\", O_RDWR | O_CLOEXEC);\n+    if (s->ne_fd < 0) {\n+        error_report(\"nitro: failed to open /dev/nitro_enclaves: %s\",\n+                     strerror(errno));\n+        return -errno;\n+    }\n+\n+    ret = ioctl(s->ne_fd, NE_CREATE_VM, &slot_uid);\n+    if (ret < 0) {\n+        error_report(\"nitro: NE_CREATE_VM failed: %s\", strerror(errno));\n+        close(s->ne_fd);\n+        return -errno;\n+    }\n+    s->enclave_fd = ret;\n+    s->slot_uid = slot_uid;\n+\n+    return 0;\n+}\n+\n+static int nitro_donate_ram_block(RAMBlock *rb, void *opaque)\n+{\n+    NitroAccelState *s = opaque;\n+    struct ne_user_memory_region region = {\n+        .flags = 0,\n+        .memory_size = rb->used_length,\n+        .userspace_addr = (uint64_t)(uintptr_t)rb->host,\n+    };\n+\n+    if (!rb->used_length) {\n+        return 0;\n+    }\n+\n+    if (ioctl(s->enclave_fd, NE_SET_USER_MEMORY_REGION, &region) < 0) {\n+        error_report(\"nitro: NE_SET_USER_MEMORY_REGION failed for %s \"\n+                     \"(%\" PRIu64 \" bytes): %s\", rb->idstr, rb->used_length,\n+                     strerror(errno));\n+        return -errno;\n+    }\n+    return 0;\n+}\n+\n+/*\n+ * Start the Enclave. This gets called when the first vCPU 0 enters its main\n+ * loop. At this point memory is set up and the EIF is loaded. This function\n+ * donates memory, adds vCPUs, and starts the enclave.\n+ */\n+static void nitro_do_start(NitroAccelState *s)\n+{\n+    MachineState *ms = MACHINE(qdev_get_machine());\n+    int nr_cpus = ms->smp.cpus;\n+    int i, ret;\n+    struct ne_enclave_start_info start_info = {\n+        .flags = s->debug_mode ? NE_ENCLAVE_DEBUG_MODE : 0,\n+        .enclave_cid = s->enclave_cid,\n+    };\n+\n+    ret = qemu_ram_foreach_block(nitro_donate_ram_block, s);\n+    if (ret < 0) {\n+        error_report(\"nitro: failed to donate memory\");\n+        exit(1);\n+    }\n+\n+    for (i = 0; i < nr_cpus; i++) {\n+        uint32_t cpu_id = 0;\n+        if (ioctl(s->enclave_fd, NE_ADD_VCPU, &cpu_id) < 0) {\n+            error_report(\"nitro: NE_ADD_VCPU failed: %s\", strerror(errno));\n+            exit(1);\n+        }\n+    }\n+\n+    ret = ioctl(s->enclave_fd, NE_START_ENCLAVE, &start_info);\n+    if (ret < 0) {\n+        switch (errno) {\n+        case NE_ERR_NO_MEM_REGIONS_ADDED:\n+            error_report(\"nitro: no memory regions added\");\n+            break;\n+        case NE_ERR_NO_VCPUS_ADDED:\n+            error_report(\"nitro: no vCPUs added\");\n+            break;\n+        case NE_ERR_ENCLAVE_MEM_MIN_SIZE:\n+            error_report(\"nitro: memory is below the minimum \"\n+                         \"required size. Try increasing -m\");\n+            break;\n+        case NE_ERR_FULL_CORES_NOT_USED:\n+            error_report(\"nitro: requires full CPU cores. \"\n+                         \"Try increasing -smp to a multiple of threads \"\n+                         \"per core on this host (e.g. -smp 2)\");\n+            break;\n+        case NE_ERR_NOT_IN_INIT_STATE:\n+            error_report(\"nitro: not in init state\");\n+            break;\n+        case NE_ERR_INVALID_FLAG_VALUE:\n+            error_report(\"nitro: invalid flag value for NE_START_ENCLAVE\");\n+            break;\n+        case NE_ERR_INVALID_ENCLAVE_CID:\n+            error_report(\"nitro: invalid enclave CID\");\n+            break;\n+        default:\n+            error_report(\"nitro: NE_START_ENCLAVE failed: %s (errno %d)\",\n+                         strerror(errno), errno);\n+            break;\n+        }\n+        exit(1);\n+    }\n+\n+    s->enclave_cid = start_info.enclave_cid;\n+    trace_nitro_enclave_started(s->enclave_cid);\n+\n+    /*\n+     * Push enclave CID to all devices that need it.\n+     * Each device handles its own connection (console, heartbeat).\n+     */\n+    {\n+        BusState *sysbus = sysbus_get_default();\n+        BusChild *kid;\n+\n+        QTAILQ_FOREACH(kid, &sysbus->children, sibling) {\n+            DeviceState *dev = kid->child;\n+            if (object_property_find(OBJECT(dev), \"enclave-cid\")) {\n+                object_property_set_uint(OBJECT(dev), \"enclave-cid\",\n+                                         s->enclave_cid, NULL);\n+            }\n+        }\n+    }\n+}\n+\n+/*\n+ * vCPU dummy thread function. The real vCPUs run inside the enclave.\n+ *\n+ * Based on dummy_cpu_thread_fn() from accel/dummy-cpus.c.\n+ */\n+static void *nitro_vcpu_thread_fn(void *arg)\n+{\n+    CPUState *cpu = arg;\n+    NitroAccelState *s = NITRO_ACCEL(current_accel());\n+    sigset_t waitset;\n+\n+    rcu_register_thread();\n+\n+    bql_lock();\n+    qemu_thread_get_self(cpu->thread);\n+    cpu->thread_id = qemu_get_thread_id();\n+    current_cpu = cpu;\n+\n+    sigemptyset(&waitset);\n+    sigaddset(&waitset, SIG_IPI);\n+\n+    cpu_thread_signal_created(cpu);\n+    qemu_guest_random_seed_thread_part2(cpu->random_seed);\n+\n+    /* vCPU 0 starts the enclave on first entry */\n+    if (cpu->cpu_index == 0) {\n+        nitro_do_start(s);\n+    }\n+\n+    do {\n+        qemu_process_cpu_events(cpu);\n+        bql_unlock();\n+        {\n+            int sig;\n+            while (sigwait(&waitset, &sig) == -1 &&\n+                   (errno == EAGAIN || errno == EINTR)) {\n+                /* retry */\n+            }\n+        }\n+        bql_lock();\n+    } while (!cpu->unplug);\n+\n+    bql_unlock();\n+    rcu_unregister_thread();\n+    return NULL;\n+}\n+\n+static void nitro_start_vcpu_thread(CPUState *cpu)\n+{\n+    char thread_name[VCPU_THREAD_NAME_SIZE];\n+\n+    snprintf(thread_name, VCPU_THREAD_NAME_SIZE, \"CPU %d/Nitro\",\n+             cpu->cpu_index);\n+    qemu_thread_create(cpu->thread, thread_name, nitro_vcpu_thread_fn,\n+                       cpu, QEMU_THREAD_JOINABLE);\n+}\n+\n+/* QOM properties */\n+\n+static bool nitro_get_debug_mode(Object *obj, Error **errp)\n+{\n+    return NITRO_ACCEL(obj)->debug_mode;\n+}\n+\n+static void nitro_set_debug_mode(Object *obj, bool value, Error **errp)\n+{\n+    NITRO_ACCEL(obj)->debug_mode = value;\n+}\n+\n+static void nitro_get_enclave_cid(Object *obj, Visitor *v,\n+                                  const char *name, void *opaque,\n+                                  Error **errp)\n+{\n+    uint64_t val = NITRO_ACCEL(obj)->enclave_cid;\n+    visit_type_uint64(v, name, &val, errp);\n+}\n+\n+static void nitro_set_enclave_cid(Object *obj, Visitor *v,\n+                                  const char *name, void *opaque,\n+                                  Error **errp)\n+{\n+    uint64_t val;\n+    if (visit_type_uint64(v, name, &val, errp)) {\n+        NITRO_ACCEL(obj)->enclave_cid = val;\n+    }\n+}\n+\n+static void nitro_accel_class_init(ObjectClass *oc, const void *data)\n+{\n+    AccelClass *ac = ACCEL_CLASS(oc);\n+    ac->name = \"Nitro\";\n+    ac->init_machine = nitro_init_machine;\n+    ac->allowed = &nitro_allowed;\n+\n+    object_class_property_add_bool(oc, \"debug-mode\",\n+                                   nitro_get_debug_mode,\n+                                   nitro_set_debug_mode);\n+    object_class_property_set_description(oc, \"debug-mode\",\n+        \"Start enclave in debug mode (enables console output)\");\n+\n+    object_class_property_add(oc, \"enclave-cid\", \"uint64\",\n+                              nitro_get_enclave_cid,\n+                              nitro_set_enclave_cid,\n+                              NULL, NULL);\n+    object_class_property_set_description(oc, \"enclave-cid\",\n+        \"Enclave CID (0 = auto-assigned by Nitro)\");\n+}\n+\n+static const TypeInfo nitro_accel_type = {\n+    .name = TYPE_NITRO_ACCEL,\n+    .parent = TYPE_ACCEL,\n+    .instance_size = sizeof(NitroAccelState),\n+    .class_init = nitro_accel_class_init,\n+};\n+module_obj(TYPE_NITRO_ACCEL);\n+\n+static void nitro_accel_ops_class_init(ObjectClass *oc, const void *data)\n+{\n+    AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);\n+    ops->create_vcpu_thread = nitro_start_vcpu_thread;\n+    ops->handle_interrupt = generic_handle_interrupt;\n+}\n+\n+static const TypeInfo nitro_accel_ops_type = {\n+    .name = ACCEL_OPS_NAME(\"nitro\"),\n+    .parent = TYPE_ACCEL_OPS,\n+    .class_init = nitro_accel_ops_class_init,\n+    .abstract = true,\n+};\n+module_obj(ACCEL_OPS_NAME(\"nitro\"));\n+\n+static void nitro_type_init(void)\n+{\n+    type_register_static(&nitro_accel_type);\n+    type_register_static(&nitro_accel_ops_type);\n+}\n+\n+type_init(nitro_type_init);\ndiff --git a/accel/nitro/trace-events b/accel/nitro/trace-events\nnew file mode 100644\nindex 0000000000..9673eb5aa2\n--- /dev/null\n+++ b/accel/nitro/trace-events\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+#\n+# See docs/devel/tracing.rst for syntax documentation.\n+\n+# nitro-accel.c\n+nitro_enclave_started(uint64_t cid) \"nitro: enclave started, CID=%\"PRIu64\ndiff --git a/accel/nitro/trace.h b/accel/nitro/trace.h\nnew file mode 100644\nindex 0000000000..8c5564725d\n--- /dev/null\n+++ b/accel/nitro/trace.h\n@@ -0,0 +1,2 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+#include \"trace/trace-accel_nitro.h\"\ndiff --git a/accel/stubs/meson.build b/accel/stubs/meson.build\nindex 48eccd1b86..5de4a279ff 100644\n--- a/accel/stubs/meson.build\n+++ b/accel/stubs/meson.build\n@@ -3,6 +3,7 @@ system_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_HVF', if_false: files('hvf-stub.c'))\n+system_stubs_ss.add(when: 'CONFIG_NITRO', if_false: files('nitro-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_NVMM', if_false: files('nvmm-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_WHPX', if_false: files('whpx-stub.c'))\n system_stubs_ss.add(when: 'CONFIG_MSHV', if_false: files('mshv-stub.c'))\ndiff --git a/accel/stubs/nitro-stub.c b/accel/stubs/nitro-stub.c\nnew file mode 100644\nindex 0000000000..186c8444f8\n--- /dev/null\n+++ b/accel/stubs/nitro-stub.c\n@@ -0,0 +1,11 @@\n+/*\n+ * Nitro accel stubs for QEMU\n+ *\n+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#include \"qemu/osdep.h\"\n+\n+bool nitro_allowed;\ndiff --git a/include/system/hw_accel.h b/include/system/hw_accel.h\nindex 628a50e066..f0c10b6d80 100644\n--- a/include/system/hw_accel.h\n+++ b/include/system/hw_accel.h\n@@ -17,6 +17,7 @@\n #include \"system/mshv.h\"\n #include \"system/whpx.h\"\n #include \"system/nvmm.h\"\n+#include \"system/nitro-accel.h\"\n \n /**\n  * cpu_synchronize_state:\ndiff --git a/include/system/nitro-accel.h b/include/system/nitro-accel.h\nnew file mode 100644\nindex 0000000000..a93aa6fb00\n--- /dev/null\n+++ b/include/system/nitro-accel.h\n@@ -0,0 +1,25 @@\n+/*\n+ * Nitro Enclaves accelerator - public interface\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#ifndef SYSTEM_NITRO_ACCEL_H\n+#define SYSTEM_NITRO_ACCEL_H\n+\n+#include \"qemu/accel.h\"\n+\n+extern bool nitro_allowed;\n+\n+static inline bool nitro_enabled(void)\n+{\n+    return nitro_allowed;\n+}\n+\n+#define TYPE_NITRO_ACCEL ACCEL_CLASS_NAME(\"nitro\")\n+\n+typedef struct NitroAccelState NitroAccelState;\n+DECLARE_INSTANCE_CHECKER(NitroAccelState, NITRO_ACCEL,\n+                         TYPE_NITRO_ACCEL)\n+\n+#endif /* SYSTEM_NITRO_ACCEL_H */\ndiff --git a/meson.build b/meson.build\nindex 4af32c3e1f..bdeee65db2 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -302,11 +302,13 @@ accelerator_targets += { 'CONFIG_XEN': xen_targets }\n if cpu == 'aarch64'\n   accelerator_targets += {\n     'CONFIG_HVF': ['aarch64-softmmu'],\n+    'CONFIG_NITRO': ['aarch64-softmmu'],\n     'CONFIG_WHPX': ['aarch64-softmmu']\n   }\n elif cpu == 'x86_64'\n   accelerator_targets += {\n     'CONFIG_HVF': ['x86_64-softmmu'],\n+    'CONFIG_NITRO': ['x86_64-softmmu'],\n     'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'],\n     'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'],\n     'CONFIG_MSHV': ['x86_64-softmmu'],\n@@ -881,6 +883,11 @@ if get_option('hvf').allowed()\n   endif\n endif\n \n+nitro = not_found\n+if get_option('nitro').allowed() and host_os == 'linux'\n+  accelerators += 'CONFIG_NITRO'\n+endif\n+\n nvmm = not_found\n if host_os == 'netbsd'\n   nvmm = cc.find_library('nvmm', required: get_option('nvmm'))\n@@ -922,6 +929,9 @@ endif\n if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled()\n   error('HVF not available on this platform')\n endif\n+if 'CONFIG_NITRO' not in accelerators and get_option('nitro').enabled()\n+  error('NITRO not available on this platform')\n+endif\n if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled()\n   error('NVMM not available on this platform')\n endif\n@@ -3593,6 +3603,7 @@ if have_system\n     'accel/hvf',\n     'accel/kvm',\n     'accel/mshv',\n+    'accel/nitro',\n     'audio',\n     'backends',\n     'backends/tpm',\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 2836156257..31d5916cfc 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -79,6 +79,8 @@ option('whpx', type: 'feature', value: 'auto',\n        description: 'WHPX acceleration support')\n option('hvf', type: 'feature', value: 'auto',\n        description: 'HVF acceleration support')\n+option('nitro', type: 'feature', value: 'auto',\n+       description: 'Nitro acceleration support')\n option('nvmm', type: 'feature', value: 'auto',\n        description: 'NVMM acceleration support')\n option('xen', type: 'feature', value: 'auto',\ndiff --git a/qemu-options.hx b/qemu-options.hx\nindex 33fcfe7ce6..9b6fb247f7 100644\n--- a/qemu-options.hx\n+++ b/qemu-options.hx\n@@ -28,7 +28,7 @@ DEF(\"machine\", HAS_ARG, QEMU_OPTION_machine, \\\n     \"-machine [type=]name[,prop[=value][,...]]\\n\"\n     \"                selects emulated machine ('-machine help' for list)\\n\"\n     \"                property accel=accel1[:accel2[:...]] selects accelerator\\n\"\n-    \"                supported accelerators are kvm, xen, hvf, nvmm, whpx, mshv or tcg (default: tcg)\\n\"\n+    \"                supported accelerators are kvm, xen, hvf, nitro, nvmm, whpx, mshv or tcg (default: tcg)\\n\"\n     \"                vmport=on|off|auto controls emulation of vmport (default: auto)\\n\"\n     \"                dump-guest-core=on|off include guest memory in a core dump (default=on)\\n\"\n     \"                mem-merge=on|off controls memory merge support (default: on)\\n\"\n@@ -67,7 +67,7 @@ SRST\n \n     ``accel=accels1[:accels2[:...]]``\n         This is used to enable an accelerator. Depending on the target\n-        architecture, kvm, xen, hvf, nvmm, whpx, mshv or tcg can be\n+        architecture, kvm, xen, hvf, nitro, nvmm, whpx, mshv or tcg can be\n         available. By default, tcg is used. If there is more than one\n         accelerator specified, the next one is used if the previous one\n         fails to initialize.\n@@ -228,7 +228,7 @@ ERST\n \n DEF(\"accel\", HAS_ARG, QEMU_OPTION_accel,\n     \"-accel [accel=]accelerator[,prop[=value][,...]]\\n\"\n-    \"                select accelerator (kvm, xen, hvf, nvmm, whpx, mshv or tcg; use 'help' for a list)\\n\"\n+    \"                select accelerator (kvm, xen, hvf, nitro, nvmm, whpx, mshv or tcg; use 'help' for a list)\\n\"\n     \"                igd-passthru=on|off (enable Xen integrated Intel graphics passthrough, default=off)\\n\"\n     \"                kernel-irqchip=on|off|split controls accelerated irqchip support (default=on)\\n\"\n     \"                kvm-shadow-mem=size of KVM shadow MMU in bytes\\n\"\n@@ -243,7 +243,7 @@ DEF(\"accel\", HAS_ARG, QEMU_OPTION_accel,\n SRST\n ``-accel name[,prop=value[,...]]``\n     This is used to enable an accelerator. Depending on the target\n-    architecture, kvm, xen, hvf, nvmm, whpx, mshv or tcg can be available.\n+    architecture, kvm, xen, hvf, nitro, nvmm, whpx, mshv or tcg can be available.\n     By default, tcg is used. If there is more than one accelerator\n     specified, the next one is used if the previous one fails to\n     initialize.\ndiff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh\nindex e8edc5252a..ca5b113119 100644\n--- a/scripts/meson-buildoptions.sh\n+++ b/scripts/meson-buildoptions.sh\n@@ -158,6 +158,7 @@ meson_options_help() {\n   printf \"%s\\n\" '  multiprocess    Out of process device emulation support'\n   printf \"%s\\n\" '  netmap          netmap network backend support'\n   printf \"%s\\n\" '  nettle          nettle cryptography support'\n+  printf \"%s\\n\" '  nitro           Nitro acceleration support'\n   printf \"%s\\n\" '  numa            libnuma support'\n   printf \"%s\\n\" '  nvmm            NVMM acceleration support'\n   printf \"%s\\n\" '  opengl          OpenGL support'\n@@ -418,6 +419,8 @@ _meson_option_parse() {\n     --disable-netmap) printf \"%s\" -Dnetmap=disabled ;;\n     --enable-nettle) printf \"%s\" -Dnettle=enabled ;;\n     --disable-nettle) printf \"%s\" -Dnettle=disabled ;;\n+    --enable-nitro) printf \"%s\" -Dnitro=enabled ;;\n+    --disable-nitro) printf \"%s\" -Dnitro=disabled ;;\n     --enable-numa) printf \"%s\" -Dnuma=enabled ;;\n     --disable-numa) printf \"%s\" -Dnuma=disabled ;;\n     --enable-nvmm) printf \"%s\" -Dnvmm=enabled ;;\n","prefixes":["03/10"]}