From nobody Sun Apr 12 06:07:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@amazon.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=amazon.com ARC-Seal: i=1; a=rsa-sha256; t=1771379642; cv=none; d=zohomail.com; s=zohoarc; b=V7dHo8knAXGMV329ypLW01bk4U7bfJlAynkIKvzT8UzUuidhW5385H/m8E8S0141v9QkW/BWUcUpeLAn83Rni39wHKrCYjzCdpgd4V5m9TdtDY8Y3dpJSrdpogdjMJcDBgj0KjOVUx4As/EUOFfp6sfxg+XN02cbEYbA1zaxC6c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1771379642; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+ywOER5w8TwL0tvTjS30yhRwjSLriESD5O4Ff5/Ir0A=; b=mcTR40SRn63d23jkrZ4ELJEeAUHnfdebvfQpbUgM0Qa0unZF6/D6I+fnQggEyH5eYWFsELWTUh2rvaklnOYbvyHV9vol6J0TpBtkyv8f+Fac/RYrxuIlr94xf6QkGbPwxtFuO4tvvHixoPrxaSuS2GLkS/WKjIrLjyyogJHruBc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@amazon.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771379642333244.94606973705618; Tue, 17 Feb 2026 17:54:02 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vsWk0-0007DZ-5g; Tue, 17 Feb 2026 20:52:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vsWjy-0007Ch-4M; Tue, 17 Feb 2026 20:52:34 -0500 Received: from pdx-out-005.esa.us-west-2.outbound.mail-perimeter.amazon.com ([52.13.214.179]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vsWjw-0005F9-8M; Tue, 17 Feb 2026 20:52:33 -0500 Received: from ip-10-5-12-219.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.12.219]) by internal-pdx-out-005.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2026 01:52:30 +0000 Received: from EX19MTAUWA002.ant.amazon.com [205.251.233.178:6876] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.11.41:2525] with esmtp (Farcaster) id ca057405-e70c-4233-bf8a-611952cc798d; Wed, 18 Feb 2026 01:52:30 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWA002.ant.amazon.com (10.250.64.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.35; Wed, 18 Feb 2026 01:52:30 +0000 Received: from ip-10-253-83-51.amazon.com (172.19.99.218) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.35; Wed, 18 Feb 2026 01:52:27 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1771379552; x=1802915552; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+ywOER5w8TwL0tvTjS30yhRwjSLriESD5O4Ff5/Ir0A=; b=KU5FscUrBkvD7G+zwwsWXsnQOQkVN9lcyNnj6O+7T+BGT+d20vwNQrpX kMlXHAPiQdyFD0nD20a9iwNyw4YW10K+jv7MykLtPNtD5NUKUpDMHssPO oSWxBTNtxdUui/b6TuF2t4dKffrEa/WmJmeHpvS3FLgsJm5YXi8CNJzsZ i4rXaaotE+cY5vrAHqsRWgT20SeDobvaIarDuAk8Ji0O3XfovW+svmHfr 268yS+8PsDT6CN4Tg6Rd9sG6XJfbf6zkYTH4H3agD6Bijb4niSJ33IIiE SLGbz00YS9MKwlw1Z1Xe9EbYFsSjYiBIhaKhoGnqoupyu/hn57jmu5rJt g==; X-CSE-ConnectionGUID: YH57NK7PQpGG/VxtznZkfg== X-CSE-MsgGUID: s/CFC8JTSqOlx1Id+lLljQ== X-IronPort-AV: E=Sophos;i="6.21,297,1763424000"; d="scan'208";a="13261398" X-Farcaster-Flow-ID: ca057405-e70c-4233-bf8a-611952cc798d From: Alexander Graf To: CC: , Peter Maydell , "Thomas Huth" , , , , , Cornelia Huck , , Dorjoy Chowdhury , Pierrick Bouvier , Paolo Bonzini , Tyler Fanelli , , Subject: [PATCH 05/10] hw/nitro: Introduce Nitro Enclave Heartbeat device Date: Wed, 18 Feb 2026 01:51:45 +0000 Message-ID: <20260218015151.4052-6-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 EX19D020UWC004.ant.amazon.com (10.13.138.149) Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=52.13.214.179; envelope-from=prvs=502105d20=graf@amazon.de; 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, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, T_SPF_PERMERROR=0.01, 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amazon.com) X-ZM-MESSAGEID: 1771379643657158500 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 --- 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 =C2=A9 2026 Amazon.com, Inc. or its affiliates. All Rights Re= served. + * + * Authors: + * Alexander Graf + * + * 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 =3D 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 siz= e) +{ + NitroHeartbeatState *s =3D 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 =3D 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 =3D NITRO_HEARTBEAT(dev); + g_autofree char *chardev_id =3D NULL; + Chardev *chr; + ChardevBackend *backend; + ChardevSocket *sock; + + chardev_id =3D g_strdup_printf("nitro-heartbeat"); + + backend =3D g_new0(ChardevBackend, 1); + backend->type =3D CHARDEV_BACKEND_KIND_SOCKET; + sock =3D backend->u.socket.data =3D g_new0(ChardevSocket, 1); + sock->addr =3D g_new0(SocketAddressLegacy, 1); + sock->addr->type =3D SOCKET_ADDRESS_TYPE_VSOCK; + sock->addr->u.vsock.data =3D g_new0(VsockSocketAddress, 1); + sock->addr->u.vsock.data->cid =3D g_strdup(VMADDR_CID_ANY_STR); + sock->addr->u.vsock.data->port =3D g_strdup_printf("%u", HEARTBEAT_POR= T); + sock->server =3D true; + sock->has_server =3D true; + sock->wait =3D false; + sock->has_wait =3D true; + + chr =3D 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 =3D DEVICE_CLASS(oc); + + dc->realize =3D nitro_heartbeat_realize; +} + +static const TypeInfo nitro_heartbeat_info =3D { + .name =3D TYPE_NITRO_HEARTBEAT, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(NitroHeartbeatState), + .class_init =3D 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-vs= ock.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 @@ =20 # 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 */ --=20 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