@samitouri / QOSamiQemu / commits / 00c8360720

hw/nitro/nitro-serial-vsock: Nitro Enclaves vsock console

Nitro Enclaves support a special "debug" mode. When in debug mode, the Nitro Hypervisor provides a vsock port that the parent can connect to to receive serial console output of the Enclave. Add a new nitro-serial-vsock driver that implements short-circuit logic to establish the vsock connection to that port and feed its data into a chardev, so that a machine model can use it as serial device. Signed-off-by: Alexander Graf <graf@amazon.com> Link: https://lore.kernel.org/r/20260225220807.33092-6-graf@amazon.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Alexander Graf committed Feb 25, 2026 at 22:07 UTC 00c83607206c0d98e40fc71f78713276e03489db
5 files changed +154
hw/nitro/Kconfig
+4
@@ -1,2 +1,6 @@
1 config NITRO_VSOCK_BUS
2 bool
3 +
4 +config NITRO_SERIAL_VSOCK
5 + bool
6 + depends on NITRO_VSOCK_BUS
hw/nitro/meson.build
+1
@@ -1 +1,2 @@
1 system_ss.add(when: 'CONFIG_NITRO_VSOCK_BUS', if_true: files('nitro-vsock-bus.c'))
2 +system_ss.add(when: 'CONFIG_NITRO_SERIAL_VSOCK', if_true: files('serial-vsock.c'))
hw/nitro/serial-vsock.c new
+123
@@ -0,0 +1,123 @@
1 +/*
2 + * Nitro Enclave Vsock Serial
3 + *
4 + * Copyright © 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 + *
6 + * Authors:
7 + * Alexander Graf <graf@amazon.com>
8 + *
9 + * With Nitro Enclaves in debug mode, the Nitro Hypervisor provides a vsock
10 + * port that the parent can connect to to receive serial console output of
11 + * the Enclave. This driver implements short-circuit logic to establish the
12 + * vsock connection to that port and feed its data into a chardev, so that
13 + * a machine model can use it as serial device.
14 + *
15 + * SPDX-License-Identifier: GPL-2.0-or-later
16 + */
17 +
18 +#include "qemu/osdep.h"
19 +#include "qemu/error-report.h"
20 +#include "qapi/error.h"
21 +#include "chardev/char.h"
22 +#include "chardev/char-fe.h"
23 +#include "hw/core/qdev-properties.h"
24 +#include "hw/core/qdev-properties-system.h"
25 +#include "hw/nitro/serial-vsock.h"
26 +#include "trace.h"
27 +
28 +#define CONSOLE_PORT_START 10000
29 +#define VMADDR_CID_HYPERVISOR_STR "0"
30 +
31 +static int nitro_serial_vsock_can_read(void *opaque)
32 +{
33 + NitroSerialVsockState *s = opaque;
34 +
35 + /* Refuse vsock input until the output backend is ready */
36 + return qemu_chr_fe_backend_open(&s->output) ? 4096 : 0;
37 +}
38 +
39 +static void nitro_serial_vsock_read(void *opaque, const uint8_t *buf, int size)
40 +{
41 + NitroSerialVsockState *s = opaque;
42 +
43 + /* Forward all vsock data to the output chardev */
44 + qemu_chr_fe_write_all(&s->output, buf, size);
45 +}
46 +
47 +static void nitro_serial_vsock_event(void *opaque, QEMUChrEvent event)
48 +{
49 + /* No need to action on connect/disconnect events, but trace for debug */
50 + trace_nitro_serial_vsock_event(event);
51 +}
52 +
53 +static void nitro_serial_vsock_enclave_started(NitroVsockDevice *dev,
54 + uint32_t enclave_cid,
55 + Error **errp)
56 +{
57 + NitroSerialVsockState *s = NITRO_SERIAL_VSOCK(dev);
58 + uint32_t port = enclave_cid + CONSOLE_PORT_START;
59 + g_autofree char *chardev_id = NULL;
60 + Chardev *chr;
61 + ChardevBackend *backend;
62 + ChardevSocket *sock;
63 +
64 + /*
65 + * We know the Enclave CID to connect to now. Create a vsock
66 + * client chardev that connects to the Enclave's console.
67 + */
68 + chardev_id = g_strdup_printf("nitro-console-%u", enclave_cid);
69 +
70 + backend = g_new0(ChardevBackend, 1);
71 + backend->type = CHARDEV_BACKEND_KIND_SOCKET;
72 + sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
73 + sock->addr = g_new0(SocketAddressLegacy, 1);
74 + sock->addr->type = SOCKET_ADDRESS_TYPE_VSOCK;
75 + sock->addr->u.vsock.data = g_new0(VsockSocketAddress, 1);
76 + sock->addr->u.vsock.data->cid = g_strdup(VMADDR_CID_HYPERVISOR_STR);
77 + sock->addr->u.vsock.data->port = g_strdup_printf("%u", port);
78 + sock->server = false;
79 + sock->has_server = true;
80 +
81 + chr = qemu_chardev_new(chardev_id, TYPE_CHARDEV_SOCKET,
82 + backend, NULL, errp);
83 + if (!chr) {
84 + return;
85 + }
86 +
87 + if (!qemu_chr_fe_init(&s->vsock, chr, errp)) {
88 + return;
89 + }
90 +
91 + qemu_chr_fe_set_handlers(&s->vsock,
92 + nitro_serial_vsock_can_read,
93 + nitro_serial_vsock_read,
94 + nitro_serial_vsock_event,
95 + NULL, s, NULL, true);
96 +}
97 +
98 +static const Property nitro_serial_vsock_props[] = {
99 + DEFINE_PROP_CHR("chardev", NitroSerialVsockState, output),
100 +};
101 +
102 +static void nitro_serial_vsock_class_init(ObjectClass *oc, const void *data)
103 +{
104 + DeviceClass *dc = DEVICE_CLASS(oc);
105 + NitroVsockDeviceClass *ndc = NITRO_VSOCK_DEVICE_CLASS(oc);
106 +
107 + device_class_set_props(dc, nitro_serial_vsock_props);
108 + ndc->enclave_started = nitro_serial_vsock_enclave_started;
109 +}
110 +
111 +static const TypeInfo nitro_serial_vsock_info = {
112 + .name = TYPE_NITRO_SERIAL_VSOCK,
113 + .parent = TYPE_NITRO_VSOCK_DEVICE,
114 + .instance_size = sizeof(NitroSerialVsockState),
115 + .class_init = nitro_serial_vsock_class_init,
116 +};
117 +
118 +static void nitro_serial_vsock_register(void)
119 +{
120 + type_register_static(&nitro_serial_vsock_info);
121 +}
122 +
123 +type_init(nitro_serial_vsock_register);
hw/nitro/trace-events
+2
@@ -1,2 +1,4 @@
1 # See docs/devel/tracing.rst for syntax documentation.
2
3 +# serial-vsock.c
4 +nitro_serial_vsock_event(int event) "event %d"
include/hw/nitro/serial-vsock.h new
+24
@@ -0,0 +1,24 @@
1 +/*
2 + * Nitro Enclave Serial (vsock)
3 + *
4 + * SPDX-License-Identifier: GPL-2.0-or-later
5 + */
6 +
7 +#ifndef HW_CHAR_NITRO_SERIAL_VSOCK_H
8 +#define HW_CHAR_NITRO_SERIAL_VSOCK_H
9 +
10 +#include "hw/nitro/nitro-vsock-bus.h"
11 +#include "chardev/char-fe.h"
12 +#include "qom/object.h"
13 +
14 +#define TYPE_NITRO_SERIAL_VSOCK "nitro-serial-vsock"
15 +OBJECT_DECLARE_SIMPLE_TYPE(NitroSerialVsockState, NITRO_SERIAL_VSOCK)
16 +
17 +struct NitroSerialVsockState {
18 + NitroVsockDevice parent_obj;
19 +
20 + CharFrontend output; /* chardev to write console output to */
21 + CharFrontend vsock; /* vsock chardev to enclave console */
22 +};
23 +
24 +#endif /* HW_CHAR_NITRO_SERIAL_VSOCK_H */