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 05/10] hw/nitro: Introduce Nitro Enclave Heartbeat device
Date: Wed, 18 Feb 2026 01:51:45 +0000 [thread overview]
Message-ID: <20260218015151.4052-6-graf@amazon.com> (raw)
In-Reply-To: <20260218015151.4052-1-graf@amazon.com>
Nitro Enclaves expect the parent instance to host a vsock heartbeat listener
at port 9000. To host a Nitro Enclave with the nitro accel in QEMU, add
such a heartbeat listener as device model, so that the machine can
easily instantiate it.
Signed-off-by: Alexander Graf <graf@amazon.com>
---
hw/nitro/Kconfig | 4 ++
hw/nitro/heartbeat.c | 115 +++++++++++++++++++++++++++++++++++
hw/nitro/meson.build | 1 +
hw/nitro/trace-events | 4 ++
include/hw/nitro/heartbeat.h | 25 ++++++++
5 files changed, 149 insertions(+)
create mode 100644 hw/nitro/heartbeat.c
create mode 100644 include/hw/nitro/heartbeat.h
diff --git a/hw/nitro/Kconfig b/hw/nitro/Kconfig
index 86c817c766..6fe050d35d 100644
--- a/hw/nitro/Kconfig
+++ b/hw/nitro/Kconfig
@@ -1,3 +1,7 @@
config NITRO_SERIAL_VSOCK
bool
depends on NITRO
+
+config NITRO_HEARTBEAT
+ bool
+ depends on NITRO
diff --git a/hw/nitro/heartbeat.c b/hw/nitro/heartbeat.c
new file mode 100644
index 0000000000..3d2a371098
--- /dev/null
+++ b/hw/nitro/heartbeat.c
@@ -0,0 +1,115 @@
+/*
+ * Nitro Enclave Heartbeat device
+ *
+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors:
+ * Alexander Graf <graf@amazon.com>
+ *
+ * The Nitro Enclave init process sends a heartbeat byte (0xB7) to
+ * CID 3 (parent) port 9000 on boot to signal it reached initramfs.
+ * The parent must accept the connection, read the byte, and echo it
+ * back. If the enclave init cannot reach the listener, it exits.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "hw/nitro/heartbeat.h"
+#include "trace.h"
+
+#define HEARTBEAT_PORT 9000
+#define VMADDR_CID_ANY_STR "4294967295"
+
+static int nitro_heartbeat_can_read(void *opaque)
+{
+ NitroHeartbeatState *s = opaque;
+
+ /* One-shot protocol: stop reading after the first heartbeat */
+ return s->done ? 0 : 1;
+}
+
+static void nitro_heartbeat_read(void *opaque, const uint8_t *buf, int size)
+{
+ NitroHeartbeatState *s = opaque;
+
+ if (s->done || size < 1) {
+ return;
+ }
+
+ /* Echo the heartbeat byte back and disconnect */
+ qemu_chr_fe_write_all(&s->vsock, buf, 1);
+ s->done = true;
+ qemu_chr_fe_deinit(&s->vsock, true);
+
+ trace_nitro_heartbeat_done();
+}
+
+static void nitro_heartbeat_event(void *opaque, QEMUChrEvent event)
+{
+ trace_nitro_heartbeat_event(event);
+}
+
+static void nitro_heartbeat_realize(DeviceState *dev, Error **errp)
+{
+ NitroHeartbeatState *s = NITRO_HEARTBEAT(dev);
+ g_autofree char *chardev_id = NULL;
+ Chardev *chr;
+ ChardevBackend *backend;
+ ChardevSocket *sock;
+
+ chardev_id = g_strdup_printf("nitro-heartbeat");
+
+ backend = g_new0(ChardevBackend, 1);
+ backend->type = CHARDEV_BACKEND_KIND_SOCKET;
+ sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
+ sock->addr = g_new0(SocketAddressLegacy, 1);
+ sock->addr->type = SOCKET_ADDRESS_TYPE_VSOCK;
+ sock->addr->u.vsock.data = g_new0(VsockSocketAddress, 1);
+ sock->addr->u.vsock.data->cid = g_strdup(VMADDR_CID_ANY_STR);
+ sock->addr->u.vsock.data->port = g_strdup_printf("%u", HEARTBEAT_PORT);
+ sock->server = true;
+ sock->has_server = true;
+ sock->wait = false;
+ sock->has_wait = true;
+
+ chr = qemu_chardev_new(chardev_id, TYPE_CHARDEV_SOCKET,
+ backend, NULL, errp);
+ if (!chr) {
+ return;
+ }
+
+ if (!qemu_chr_fe_init(&s->vsock, chr, errp)) {
+ return;
+ }
+
+ qemu_chr_fe_set_handlers(&s->vsock,
+ nitro_heartbeat_can_read,
+ nitro_heartbeat_read,
+ nitro_heartbeat_event,
+ NULL, s, NULL, true);
+}
+
+static void nitro_heartbeat_class_init(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = nitro_heartbeat_realize;
+}
+
+static const TypeInfo nitro_heartbeat_info = {
+ .name = TYPE_NITRO_HEARTBEAT,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NitroHeartbeatState),
+ .class_init = nitro_heartbeat_class_init,
+};
+
+static void nitro_heartbeat_register(void)
+{
+ type_register_static(&nitro_heartbeat_info);
+}
+
+type_init(nitro_heartbeat_register);
diff --git a/hw/nitro/meson.build b/hw/nitro/meson.build
index d95ed8dd79..b921da2b97 100644
--- a/hw/nitro/meson.build
+++ b/hw/nitro/meson.build
@@ -1 +1,2 @@
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'))
diff --git a/hw/nitro/trace-events b/hw/nitro/trace-events
index 20617a024a..311ab78e69 100644
--- a/hw/nitro/trace-events
+++ b/hw/nitro/trace-events
@@ -2,3 +2,7 @@
# serial-vsock.c
nitro_serial_vsock_event(int event) "event %d"
+
+# heartbeat.c
+nitro_heartbeat_event(int event) "event %d"
+nitro_heartbeat_done(void) "enclave heartbeat received"
diff --git a/include/hw/nitro/heartbeat.h b/include/hw/nitro/heartbeat.h
new file mode 100644
index 0000000000..3ed4d40bac
--- /dev/null
+++ b/include/hw/nitro/heartbeat.h
@@ -0,0 +1,25 @@
+/*
+ * Nitro Heartbeat device
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_NITRO_HEARTBEAT_H
+#define HW_MISC_NITRO_HEARTBEAT_H
+
+#include "hw/core/qdev.h"
+#include "hw/core/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_NITRO_HEARTBEAT "nitro-heartbeat"
+OBJECT_DECLARE_SIMPLE_TYPE(NitroHeartbeatState, NITRO_HEARTBEAT)
+
+struct NitroHeartbeatState {
+ SysBusDevice parent_obj;
+
+ CharFrontend vsock; /* vsock server chardev for heartbeat */
+ bool done;
+};
+
+#endif /* HW_MISC_NITRO_HEARTBEAT_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 ` Alexander Graf [this message]
2026-02-18 1:51 ` [PATCH 06/10] target/arm/cpu64: Allow -host for nitro Alexander Graf
2026-02-18 1:51 ` [PATCH 07/10] hw/nitro: Add nitro machine Alexander Graf
2026-02-18 3:27 ` 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-6-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.