1
+/*
2
+ * Nitro Enclave Vsock Bus
3
+ *
4
+ * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
+ *
6
+ * Authors:
7
+ * Alexander Graf <graf@amazon.com>
8
+ *
9
+ * A bus for Nitro Enclave vsock devices. In Nitro Enclaves, communication
10
+ * between parent and enclave/hypervisor happens almost exclusively through
11
+ * vsock. The nitro-vsock-bus models this dependency in QEMU, which allows
12
+ * devices in this bus to implement individual services on top of vsock.
13
+ *
14
+ * The nitro accel advertises the Enclave's CID to the bus by calling
15
+ * nitro_vsock_bridge_start_enclave() on the bridge device as soon as it
16
+ * knows the CID.
17
+ *
18
+ * SPDX-License-Identifier: GPL-2.0-or-later
19
+ */
20
+
21
+#include "qemu/osdep.h"
22
+#include "qapi/error.h"
23
+#include "monitor/qdev.h"
24
+#include "hw/core/sysbus.h"
25
+#include "hw/nitro/nitro-vsock-bus.h"
26
+
27
+void nitro_vsock_bridge_start_enclave(NitroVsockBridge *bridge,
28
+ uint32_t enclave_cid, Error **errp)
29
+{
30
+ ERRP_GUARD();
31
+ BusState *qbus = BUS(&bridge->bus);
32
+ BusChild *kid;
33
+
34
+ bridge->enclave_cid = enclave_cid;
35
+
36
+ QTAILQ_FOREACH(kid, &qbus->children, sibling) {
37
+ NitroVsockDevice *ndev = NITRO_VSOCK_DEVICE(kid->child);
38
+ NitroVsockDeviceClass *ndc = NITRO_VSOCK_DEVICE_GET_CLASS(ndev);
39
+
40
+ if (ndc->enclave_started) {
41
+ ndc->enclave_started(ndev, enclave_cid, errp);
42
+ if (*errp) {
43
+ return;
44
+ }
45
+ }
46
+ }
47
+}
48
+
49
+NitroVsockBridge *nitro_vsock_bridge_create(void)
50
+{
51
+ DeviceState *dev = qdev_new(TYPE_NITRO_VSOCK_BRIDGE);
52
+
53
+ qdev_set_id(dev, g_strdup("nitro-vsock"), &error_fatal);
54
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
55
+
56
+ return NITRO_VSOCK_BRIDGE(dev);
57
+}
58
+
59
+static void nitro_vsock_bridge_init(Object *obj)
60
+{
61
+ NitroVsockBridge *s = NITRO_VSOCK_BRIDGE(obj);
62
+
63
+ qbus_init(&s->bus, sizeof(s->bus), TYPE_NITRO_VSOCK_BUS,
64
+ DEVICE(s), "nitro-vsock");
65
+ object_property_add_uint32_ptr(obj, "enclave-cid",
66
+ &s->enclave_cid, OBJ_PROP_FLAG_READ);
67
+}
68
+
69
+static void nitro_vsock_device_class_init(ObjectClass *oc, const void *data)
70
+{
71
+ DeviceClass *dc = DEVICE_CLASS(oc);
72
+
73
+ dc->bus_type = TYPE_NITRO_VSOCK_BUS;
74
+}
75
+
76
+static const TypeInfo nitro_vsock_bus_types[] = {
77
+ {
78
+ .name = TYPE_NITRO_VSOCK_BUS,
79
+ .parent = TYPE_BUS,
80
+ .instance_size = sizeof(NitroVsockBus),
81
+ },
82
+ {
83
+ .name = TYPE_NITRO_VSOCK_BRIDGE,
84
+ .parent = TYPE_SYS_BUS_DEVICE,
85
+ .instance_size = sizeof(NitroVsockBridge),
86
+ .instance_init = nitro_vsock_bridge_init,
87
+ },
88
+ {
89
+ .name = TYPE_NITRO_VSOCK_DEVICE,
90
+ .parent = TYPE_DEVICE,
91
+ .instance_size = sizeof(NitroVsockDevice),
92
+ .class_size = sizeof(NitroVsockDeviceClass),
93
+ .class_init = nitro_vsock_device_class_init,
94
+ .abstract = true,
95
+ },
96
+};
97
+
98
+DEFINE_TYPES(nitro_vsock_bus_types);