xref: /qemu/hw/remote/proxy.c (revision 9f8112073aad8e485ac012ee18809457ab7f23a6)
1*9f811207SElena Ufimtseva /*
2*9f811207SElena Ufimtseva  * Copyright © 2018, 2021 Oracle and/or its affiliates.
3*9f811207SElena Ufimtseva  *
4*9f811207SElena Ufimtseva  * This work is licensed under the terms of the GNU GPL, version 2 or later.
5*9f811207SElena Ufimtseva  * See the COPYING file in the top-level directory.
6*9f811207SElena Ufimtseva  *
7*9f811207SElena Ufimtseva  */
8*9f811207SElena Ufimtseva 
9*9f811207SElena Ufimtseva #include "qemu/osdep.h"
10*9f811207SElena Ufimtseva #include "qemu-common.h"
11*9f811207SElena Ufimtseva 
12*9f811207SElena Ufimtseva #include "hw/remote/proxy.h"
13*9f811207SElena Ufimtseva #include "hw/pci/pci.h"
14*9f811207SElena Ufimtseva #include "qapi/error.h"
15*9f811207SElena Ufimtseva #include "io/channel-util.h"
16*9f811207SElena Ufimtseva #include "hw/qdev-properties.h"
17*9f811207SElena Ufimtseva #include "monitor/monitor.h"
18*9f811207SElena Ufimtseva #include "migration/blocker.h"
19*9f811207SElena Ufimtseva #include "qemu/sockets.h"
20*9f811207SElena Ufimtseva 
21*9f811207SElena Ufimtseva static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
22*9f811207SElena Ufimtseva {
23*9f811207SElena Ufimtseva     ERRP_GUARD();
24*9f811207SElena Ufimtseva     PCIProxyDev *dev = PCI_PROXY_DEV(device);
25*9f811207SElena Ufimtseva     int fd;
26*9f811207SElena Ufimtseva 
27*9f811207SElena Ufimtseva     if (!dev->fd) {
28*9f811207SElena Ufimtseva         error_setg(errp, "fd parameter not specified for %s",
29*9f811207SElena Ufimtseva                    DEVICE(device)->id);
30*9f811207SElena Ufimtseva         return;
31*9f811207SElena Ufimtseva     }
32*9f811207SElena Ufimtseva 
33*9f811207SElena Ufimtseva     fd = monitor_fd_param(monitor_cur(), dev->fd, errp);
34*9f811207SElena Ufimtseva     if (fd == -1) {
35*9f811207SElena Ufimtseva         error_prepend(errp, "proxy: unable to parse fd %s: ", dev->fd);
36*9f811207SElena Ufimtseva         return;
37*9f811207SElena Ufimtseva     }
38*9f811207SElena Ufimtseva 
39*9f811207SElena Ufimtseva     if (!fd_is_socket(fd)) {
40*9f811207SElena Ufimtseva         error_setg(errp, "proxy: fd %d is not a socket", fd);
41*9f811207SElena Ufimtseva         close(fd);
42*9f811207SElena Ufimtseva         return;
43*9f811207SElena Ufimtseva     }
44*9f811207SElena Ufimtseva 
45*9f811207SElena Ufimtseva     dev->ioc = qio_channel_new_fd(fd, errp);
46*9f811207SElena Ufimtseva 
47*9f811207SElena Ufimtseva     error_setg(&dev->migration_blocker, "%s does not support migration",
48*9f811207SElena Ufimtseva                TYPE_PCI_PROXY_DEV);
49*9f811207SElena Ufimtseva     migrate_add_blocker(dev->migration_blocker, errp);
50*9f811207SElena Ufimtseva 
51*9f811207SElena Ufimtseva     qemu_mutex_init(&dev->io_mutex);
52*9f811207SElena Ufimtseva     qio_channel_set_blocking(dev->ioc, true, NULL);
53*9f811207SElena Ufimtseva }
54*9f811207SElena Ufimtseva 
55*9f811207SElena Ufimtseva static void pci_proxy_dev_exit(PCIDevice *pdev)
56*9f811207SElena Ufimtseva {
57*9f811207SElena Ufimtseva     PCIProxyDev *dev = PCI_PROXY_DEV(pdev);
58*9f811207SElena Ufimtseva 
59*9f811207SElena Ufimtseva     if (dev->ioc) {
60*9f811207SElena Ufimtseva         qio_channel_close(dev->ioc, NULL);
61*9f811207SElena Ufimtseva     }
62*9f811207SElena Ufimtseva 
63*9f811207SElena Ufimtseva     migrate_del_blocker(dev->migration_blocker);
64*9f811207SElena Ufimtseva 
65*9f811207SElena Ufimtseva     error_free(dev->migration_blocker);
66*9f811207SElena Ufimtseva }
67*9f811207SElena Ufimtseva 
68*9f811207SElena Ufimtseva static Property proxy_properties[] = {
69*9f811207SElena Ufimtseva     DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
70*9f811207SElena Ufimtseva     DEFINE_PROP_END_OF_LIST(),
71*9f811207SElena Ufimtseva };
72*9f811207SElena Ufimtseva 
73*9f811207SElena Ufimtseva static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
74*9f811207SElena Ufimtseva {
75*9f811207SElena Ufimtseva     DeviceClass *dc = DEVICE_CLASS(klass);
76*9f811207SElena Ufimtseva     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
77*9f811207SElena Ufimtseva 
78*9f811207SElena Ufimtseva     k->realize = pci_proxy_dev_realize;
79*9f811207SElena Ufimtseva     k->exit = pci_proxy_dev_exit;
80*9f811207SElena Ufimtseva     device_class_set_props(dc, proxy_properties);
81*9f811207SElena Ufimtseva }
82*9f811207SElena Ufimtseva 
83*9f811207SElena Ufimtseva static const TypeInfo pci_proxy_dev_type_info = {
84*9f811207SElena Ufimtseva     .name          = TYPE_PCI_PROXY_DEV,
85*9f811207SElena Ufimtseva     .parent        = TYPE_PCI_DEVICE,
86*9f811207SElena Ufimtseva     .instance_size = sizeof(PCIProxyDev),
87*9f811207SElena Ufimtseva     .class_init    = pci_proxy_dev_class_init,
88*9f811207SElena Ufimtseva     .interfaces = (InterfaceInfo[]) {
89*9f811207SElena Ufimtseva         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
90*9f811207SElena Ufimtseva         { },
91*9f811207SElena Ufimtseva     },
92*9f811207SElena Ufimtseva };
93*9f811207SElena Ufimtseva 
94*9f811207SElena Ufimtseva static void pci_proxy_dev_register_types(void)
95*9f811207SElena Ufimtseva {
96*9f811207SElena Ufimtseva     type_register_static(&pci_proxy_dev_type_info);
97*9f811207SElena Ufimtseva }
98*9f811207SElena Ufimtseva 
99*9f811207SElena Ufimtseva type_init(pci_proxy_dev_register_types)
100