[PULL 033/102] hw/nitro: Add Nitro Vsock Bus

Paolo Bonzini posted 102 patches 1 month, 1 week ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Alexander Graf <graf@amazon.com>, Pedro Barbuda <pbarbuda@microsoft.com>, Mohamed Mediouni <mohamed@unpredictable.fr>, Gerd Hoffmann <kraxel@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, Dorjoy Chowdhury <dorjoychy111@gmail.com>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>, "Michael S. Tsirkin" <mst@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Bernhard Beschow <shentey@gmail.com>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, Cornelia Huck <cohuck@redhat.com>, Peter Xu <peterx@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, John Snow <jsnow@redhat.com>, Cleber Rosa <crosa@redhat.com>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>, Manos Pitsidianakis <manos.pitsidianakis@linaro.org>, "Alex Bennée" <alex.bennee@linaro.org>, Thomas Huth <thuth@redhat.com>, Ani Sinha <anisinha@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Cameron Esfahani <dirty@apple.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Wei Liu <wei.liu@kernel.org>, Marcelo Tosatti <mtosatti@redhat.com>, David Woodhouse <dwmw2@infradead.org>, Paul Durrant <paul@xen.org>, Magnus Kulke <magnus.kulke@linux.microsoft.com>, Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>
[PULL 033/102] hw/nitro: Add Nitro Vsock Bus
Posted by Paolo Bonzini 1 month, 1 week ago
From: Alexander Graf <graf@amazon.com>

Add a dedicated bus for Nitro Enclave vsock devices. In Nitro Enclaves,
communication between parent and enclave/hypervisor happens almost
exclusively through vsock. The nitro-vsock-bus models this dependency
in QEMU, which allows devices in this bus to implement individual services
on top of vsock.

The nitro machine spawns this bus by creating the included
nitro-vsock-bridge sysbus device.

The nitro accel then advertises the Enclave's CID to the bus by calling
nitro_vsock_bridge_start_enclave() on the bridge device as soon as it
knows the CID.

Nitro vsock devices can listen to that event and learn the Enclave's CID
when it is available to perform actions, such as connect to the debug
serial vsock port.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alexander Graf <graf@amazon.com>
Link: https://lore.kernel.org/r/20260225220807.33092-4-graf@amazon.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 MAINTAINERS                        |  6 ++
 meson.build                        |  1 +
 hw/nitro/trace.h                   |  4 ++
 include/hw/nitro/nitro-vsock-bus.h | 71 ++++++++++++++++++++++
 hw/nitro/nitro-vsock-bus.c         | 98 ++++++++++++++++++++++++++++++
 hw/Kconfig                         |  1 +
 hw/meson.build                     |  1 +
 hw/nitro/Kconfig                   |  2 +
 hw/nitro/meson.build               |  1 +
 hw/nitro/trace-events              |  2 +
 10 files changed, 187 insertions(+)
 create mode 100644 hw/nitro/trace.h
 create mode 100644 include/hw/nitro/nitro-vsock-bus.h
 create mode 100644 hw/nitro/nitro-vsock-bus.c
 create mode 100644 hw/nitro/Kconfig
 create mode 100644 hw/nitro/meson.build
 create mode 100644 hw/nitro/trace-events

diff --git a/MAINTAINERS b/MAINTAINERS
index 606b16762cf..d781fe59bb1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3020,6 +3020,12 @@ F: hw/vmapple/*
 F: include/hw/vmapple/*
 F: docs/system/arm/vmapple.rst
 
+Nitro Enclaves (native)
+M: Alexander Graf <graf@amazon.com>
+S: Maintained
+F: hw/nitro/
+F: include/hw/nitro/
+
 Subsystems
 ----------
 Overall Audio backends
diff --git a/meson.build b/meson.build
index 2bae618d848..f3ee08772d4 100644
--- a/meson.build
+++ b/meson.build
@@ -3620,6 +3620,7 @@ if have_system
     'hw/misc/macio',
     'hw/net',
     'hw/net/can',
+    'hw/nitro',
     'hw/nubus',
     'hw/nvme',
     'hw/nvram',
diff --git a/hw/nitro/trace.h b/hw/nitro/trace.h
new file mode 100644
index 00000000000..b455d6c17b3
--- /dev/null
+++ b/hw/nitro/trace.h
@@ -0,0 +1,4 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "trace/trace-hw_nitro.h"
diff --git a/include/hw/nitro/nitro-vsock-bus.h b/include/hw/nitro/nitro-vsock-bus.h
new file mode 100644
index 00000000000..064260aa410
--- /dev/null
+++ b/include/hw/nitro/nitro-vsock-bus.h
@@ -0,0 +1,71 @@
+/*
+ * Nitro Enclave Vsock Bus
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_NITRO_VSOCK_BUS_H
+#define HW_NITRO_VSOCK_BUS_H
+
+#include "hw/core/qdev.h"
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_NITRO_VSOCK_BUS "nitro-vsock-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(NitroVsockBus, NITRO_VSOCK_BUS)
+
+#define TYPE_NITRO_VSOCK_BRIDGE "nitro-vsock-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(NitroVsockBridge, NITRO_VSOCK_BRIDGE)
+
+#define TYPE_NITRO_VSOCK_DEVICE "nitro-vsock-device"
+OBJECT_DECLARE_TYPE(NitroVsockDevice, NitroVsockDeviceClass,
+                    NITRO_VSOCK_DEVICE)
+
+struct NitroVsockBus {
+    BusState parent_obj;
+};
+
+struct NitroVsockBridge {
+    SysBusDevice parent_obj;
+
+    NitroVsockBus bus;
+    uint32_t enclave_cid;
+};
+
+struct NitroVsockDevice {
+    DeviceState parent_obj;
+};
+
+struct NitroVsockDeviceClass {
+    DeviceClass parent_class;
+
+    /*
+     * Called after the enclave has been started and the CID is known.
+     * Devices use this to establish vsock connections to the enclave.
+     */
+    void (*enclave_started)(NitroVsockDevice *dev, uint32_t enclave_cid,
+                            Error **errp);
+};
+
+/*
+ * Machine helper to create the Nitro vsock bridge sysbus device.
+ */
+NitroVsockBridge *nitro_vsock_bridge_create(void);
+
+/*
+ * Find the Nitro vsock bridge on the sysbus.
+ */
+static inline NitroVsockBridge *nitro_vsock_bridge_find(void)
+{
+    return NITRO_VSOCK_BRIDGE(
+        object_resolve_path_type("", TYPE_NITRO_VSOCK_BRIDGE, NULL));
+}
+
+/*
+ * Notify the bridge that the enclave has started. Dispatches
+ * enclave_started() to all devices on the bus.
+ */
+void nitro_vsock_bridge_start_enclave(NitroVsockBridge *bridge,
+                                      uint32_t enclave_cid, Error **errp);
+
+#endif /* HW_NITRO_VSOCK_BUS_H */
diff --git a/hw/nitro/nitro-vsock-bus.c b/hw/nitro/nitro-vsock-bus.c
new file mode 100644
index 00000000000..eed29df512e
--- /dev/null
+++ b/hw/nitro/nitro-vsock-bus.c
@@ -0,0 +1,98 @@
+/*
+ * Nitro Enclave Vsock Bus
+ *
+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors:
+ *   Alexander Graf <graf@amazon.com>
+ *
+ * A bus for Nitro Enclave vsock devices. In Nitro Enclaves, communication
+ * between parent and enclave/hypervisor happens almost exclusively through
+ * vsock. The nitro-vsock-bus models this dependency in QEMU, which allows
+ * devices in this bus to implement individual services on top of vsock.
+ *
+ * The nitro accel advertises the Enclave's CID to the bus by calling
+ * nitro_vsock_bridge_start_enclave() on the bridge device as soon as it
+ * knows the CID.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "monitor/qdev.h"
+#include "hw/core/sysbus.h"
+#include "hw/nitro/nitro-vsock-bus.h"
+
+void nitro_vsock_bridge_start_enclave(NitroVsockBridge *bridge,
+                                      uint32_t enclave_cid, Error **errp)
+{
+    ERRP_GUARD();
+    BusState *qbus = BUS(&bridge->bus);
+    BusChild *kid;
+
+    bridge->enclave_cid = enclave_cid;
+
+    QTAILQ_FOREACH(kid, &qbus->children, sibling) {
+        NitroVsockDevice *ndev = NITRO_VSOCK_DEVICE(kid->child);
+        NitroVsockDeviceClass *ndc = NITRO_VSOCK_DEVICE_GET_CLASS(ndev);
+
+        if (ndc->enclave_started) {
+            ndc->enclave_started(ndev, enclave_cid, errp);
+            if (*errp) {
+                return;
+            }
+        }
+    }
+}
+
+NitroVsockBridge *nitro_vsock_bridge_create(void)
+{
+    DeviceState *dev = qdev_new(TYPE_NITRO_VSOCK_BRIDGE);
+
+    qdev_set_id(dev, g_strdup("nitro-vsock"), &error_fatal);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    return NITRO_VSOCK_BRIDGE(dev);
+}
+
+static void nitro_vsock_bridge_init(Object *obj)
+{
+    NitroVsockBridge *s = NITRO_VSOCK_BRIDGE(obj);
+
+    qbus_init(&s->bus, sizeof(s->bus), TYPE_NITRO_VSOCK_BUS,
+              DEVICE(s), "nitro-vsock");
+    object_property_add_uint32_ptr(obj, "enclave-cid",
+                                   &s->enclave_cid, OBJ_PROP_FLAG_READ);
+}
+
+static void nitro_vsock_device_class_init(ObjectClass *oc, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->bus_type = TYPE_NITRO_VSOCK_BUS;
+}
+
+static const TypeInfo nitro_vsock_bus_types[] = {
+    {
+        .name = TYPE_NITRO_VSOCK_BUS,
+        .parent = TYPE_BUS,
+        .instance_size = sizeof(NitroVsockBus),
+    },
+    {
+        .name = TYPE_NITRO_VSOCK_BRIDGE,
+        .parent = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(NitroVsockBridge),
+        .instance_init = nitro_vsock_bridge_init,
+    },
+    {
+        .name = TYPE_NITRO_VSOCK_DEVICE,
+        .parent = TYPE_DEVICE,
+        .instance_size = sizeof(NitroVsockDevice),
+        .class_size = sizeof(NitroVsockDeviceClass),
+        .class_init = nitro_vsock_device_class_init,
+        .abstract = true,
+    },
+};
+
+DEFINE_TYPES(nitro_vsock_bus_types);
diff --git a/hw/Kconfig b/hw/Kconfig
index f8f92b5d03d..b3ce1520a6b 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -22,6 +22,7 @@ source isa/Kconfig
 source mem/Kconfig
 source misc/Kconfig
 source net/Kconfig
+source nitro/Kconfig
 source nubus/Kconfig
 source nvme/Kconfig
 source nvram/Kconfig
diff --git a/hw/meson.build b/hw/meson.build
index 66e46b8090d..36da5322f7e 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -44,6 +44,7 @@ subdir('isa')
 subdir('mem')
 subdir('misc')
 subdir('net')
+subdir('nitro')
 subdir('nubus')
 subdir('nvme')
 subdir('nvram')
diff --git a/hw/nitro/Kconfig b/hw/nitro/Kconfig
new file mode 100644
index 00000000000..767472cb2c6
--- /dev/null
+++ b/hw/nitro/Kconfig
@@ -0,0 +1,2 @@
+config NITRO_VSOCK_BUS
+    bool
diff --git a/hw/nitro/meson.build b/hw/nitro/meson.build
new file mode 100644
index 00000000000..7e2807f1379
--- /dev/null
+++ b/hw/nitro/meson.build
@@ -0,0 +1 @@
+system_ss.add(when: 'CONFIG_NITRO_VSOCK_BUS', if_true: files('nitro-vsock-bus.c'))
diff --git a/hw/nitro/trace-events b/hw/nitro/trace-events
new file mode 100644
index 00000000000..9ccc5790487
--- /dev/null
+++ b/hw/nitro/trace-events
@@ -0,0 +1,2 @@
+# See docs/devel/tracing.rst for syntax documentation.
+
-- 
2.53.0