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