2 * Copyright © 2020, 2021 Oracle and/or its affiliates.
4 * This work is licensed under the terms of the GNU GPL-v2, version 2 or later.
6 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
11 #include "qemu-common.h"
13 #include "qemu/error-report.h"
14 #include "qemu/notify.h"
15 #include "qom/object_interfaces.h"
16 #include "hw/qdev-core.h"
17 #include "io/channel.h"
18 #include "hw/qdev-core.h"
19 #include "hw/remote/machine.h"
20 #include "io/channel-util.h"
21 #include "qapi/error.h"
22 #include "sysemu/sysemu.h"
23 #include "hw/pci/pci.h"
24 #include "qemu/sockets.h"
25 #include "monitor/monitor.h"
27 #define TYPE_REMOTE_OBJECT "x-remote-object"
28 OBJECT_DECLARE_TYPE(RemoteObject
, RemoteObjectClass
, REMOTE_OBJECT
)
30 struct RemoteObjectClass
{
31 ObjectClass parent_class
;
34 unsigned int max_devs
;
41 Notifier machine_done
;
49 DeviceListener listener
;
52 static void remote_object_set_fd(Object
*obj
, const char *str
, Error
**errp
)
54 RemoteObject
*o
= REMOTE_OBJECT(obj
);
57 fd
= monitor_fd_param(monitor_cur(), str
, errp
);
59 error_prepend(errp
, "Could not parse remote object fd %s:", str
);
63 if (!fd_is_socket(fd
)) {
64 error_setg(errp
, "File descriptor '%s' is not a socket", str
);
72 static void remote_object_set_devid(Object
*obj
, const char *str
, Error
**errp
)
74 RemoteObject
*o
= REMOTE_OBJECT(obj
);
78 o
->devid
= g_strdup(str
);
81 static void remote_object_unrealize_listener(DeviceListener
*listener
,
84 RemoteObject
*o
= container_of(listener
, RemoteObject
, listener
);
87 object_unref(OBJECT(o
));
91 static void remote_object_machine_done(Notifier
*notifier
, void *data
)
93 RemoteObject
*o
= container_of(notifier
, RemoteObject
, machine_done
);
94 DeviceState
*dev
= NULL
;
95 QIOChannel
*ioc
= NULL
;
97 RemoteCommDev
*comdev
= NULL
;
100 dev
= qdev_find_recursive(sysbus_get_default(), o
->devid
);
101 if (!dev
|| !object_dynamic_cast(OBJECT(dev
), TYPE_PCI_DEVICE
)) {
102 error_report("%s is not a PCI device", o
->devid
);
106 ioc
= qio_channel_new_fd(o
->fd
, &err
);
108 error_report_err(err
);
111 qio_channel_set_blocking(ioc
, false, NULL
);
115 o
->listener
.unrealize
= remote_object_unrealize_listener
;
116 device_listener_register(&o
->listener
);
118 /* co-routine should free this. */
119 comdev
= g_new0(RemoteCommDev
, 1);
120 *comdev
= (RemoteCommDev
) {
122 .dev
= PCI_DEVICE(dev
),
125 co
= qemu_coroutine_create(mpqemu_remote_msg_loop_co
, comdev
);
126 qemu_coroutine_enter(co
);
129 static void remote_object_init(Object
*obj
)
131 RemoteObjectClass
*k
= REMOTE_OBJECT_GET_CLASS(obj
);
132 RemoteObject
*o
= REMOTE_OBJECT(obj
);
134 if (k
->nr_devs
>= k
->max_devs
) {
135 error_report("Reached maximum number of devices: %u", k
->max_devs
);
145 o
->machine_done
.notify
= remote_object_machine_done
;
146 qemu_add_machine_init_done_notifier(&o
->machine_done
);
149 static void remote_object_finalize(Object
*obj
)
151 RemoteObjectClass
*k
= REMOTE_OBJECT_GET_CLASS(obj
);
152 RemoteObject
*o
= REMOTE_OBJECT(obj
);
154 device_listener_unregister(&o
->listener
);
157 qio_channel_shutdown(o
->ioc
, QIO_CHANNEL_SHUTDOWN_BOTH
, NULL
);
158 qio_channel_close(o
->ioc
, NULL
);
161 object_unref(OBJECT(o
->ioc
));
167 static void remote_object_class_init(ObjectClass
*klass
, void *data
)
169 RemoteObjectClass
*k
= REMOTE_OBJECT_CLASS(klass
);
172 * Limit number of supported devices to 1. This is done to avoid devices
173 * from one VM accessing the RAM of another VM. This is done until we
174 * start using separate address spaces for individual devices.
179 object_class_property_add_str(klass
, "fd", NULL
, remote_object_set_fd
);
180 object_class_property_add_str(klass
, "devid", NULL
,
181 remote_object_set_devid
);
184 static const TypeInfo remote_object_info
= {
185 .name
= TYPE_REMOTE_OBJECT
,
186 .parent
= TYPE_OBJECT
,
187 .instance_size
= sizeof(RemoteObject
),
188 .instance_init
= remote_object_init
,
189 .instance_finalize
= remote_object_finalize
,
190 .class_size
= sizeof(RemoteObjectClass
),
191 .class_init
= remote_object_class_init
,
192 .interfaces
= (InterfaceInfo
[]) {
193 { TYPE_USER_CREATABLE
},
198 static void register_types(void)
200 type_register_static(&remote_object_info
);
203 type_init(register_types
);