proxy.c (10949B)
1/* 2 * Copyright © 2018, 2021 Oracle and/or its affiliates. 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 * 7 */ 8 9#include "qemu/osdep.h" 10#include "qemu-common.h" 11 12#include "hw/remote/proxy.h" 13#include "hw/pci/pci.h" 14#include "qapi/error.h" 15#include "io/channel-util.h" 16#include "hw/qdev-properties.h" 17#include "monitor/monitor.h" 18#include "migration/blocker.h" 19#include "qemu/sockets.h" 20#include "hw/remote/mpqemu-link.h" 21#include "qemu/error-report.h" 22#include "hw/remote/proxy-memory-listener.h" 23#include "qom/object.h" 24#include "qemu/event_notifier.h" 25#include "sysemu/kvm.h" 26#include "util/event_notifier-posix.c" 27 28static void probe_pci_info(PCIDevice *dev, Error **errp); 29static void proxy_device_reset(DeviceState *dev); 30 31static void proxy_intx_update(PCIDevice *pci_dev) 32{ 33 PCIProxyDev *dev = PCI_PROXY_DEV(pci_dev); 34 PCIINTxRoute route; 35 int pin = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; 36 37 if (dev->virq != -1) { 38 kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &dev->intr, dev->virq); 39 dev->virq = -1; 40 } 41 42 route = pci_device_route_intx_to_irq(pci_dev, pin); 43 44 dev->virq = route.irq; 45 46 if (dev->virq != -1) { 47 kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &dev->intr, 48 &dev->resample, dev->virq); 49 } 50} 51 52static void setup_irqfd(PCIProxyDev *dev) 53{ 54 PCIDevice *pci_dev = PCI_DEVICE(dev); 55 MPQemuMsg msg; 56 Error *local_err = NULL; 57 58 event_notifier_init(&dev->intr, 0); 59 event_notifier_init(&dev->resample, 0); 60 61 memset(&msg, 0, sizeof(MPQemuMsg)); 62 msg.cmd = MPQEMU_CMD_SET_IRQFD; 63 msg.num_fds = 2; 64 msg.fds[0] = event_notifier_get_fd(&dev->intr); 65 msg.fds[1] = event_notifier_get_fd(&dev->resample); 66 msg.size = 0; 67 68 if (!mpqemu_msg_send(&msg, dev->ioc, &local_err)) { 69 error_report_err(local_err); 70 } 71 72 dev->virq = -1; 73 74 proxy_intx_update(pci_dev); 75 76 pci_device_set_intx_routing_notifier(pci_dev, proxy_intx_update); 77} 78 79static void pci_proxy_dev_realize(PCIDevice *device, Error **errp) 80{ 81 ERRP_GUARD(); 82 PCIProxyDev *dev = PCI_PROXY_DEV(device); 83 uint8_t *pci_conf = device->config; 84 int fd; 85 86 if (!dev->fd) { 87 error_setg(errp, "fd parameter not specified for %s", 88 DEVICE(device)->id); 89 return; 90 } 91 92 fd = monitor_fd_param(monitor_cur(), dev->fd, errp); 93 if (fd == -1) { 94 error_prepend(errp, "proxy: unable to parse fd %s: ", dev->fd); 95 return; 96 } 97 98 if (!fd_is_socket(fd)) { 99 error_setg(errp, "proxy: fd %d is not a socket", fd); 100 close(fd); 101 return; 102 } 103 104 dev->ioc = qio_channel_new_fd(fd, errp); 105 if (!dev->ioc) { 106 close(fd); 107 return; 108 } 109 110 error_setg(&dev->migration_blocker, "%s does not support migration", 111 TYPE_PCI_PROXY_DEV); 112 if (migrate_add_blocker(dev->migration_blocker, errp) < 0) { 113 error_free(dev->migration_blocker); 114 object_unref(dev->ioc); 115 return; 116 } 117 118 qemu_mutex_init(&dev->io_mutex); 119 qio_channel_set_blocking(dev->ioc, true, NULL); 120 121 pci_conf[PCI_LATENCY_TIMER] = 0xff; 122 pci_conf[PCI_INTERRUPT_PIN] = 0x01; 123 124 proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc); 125 126 setup_irqfd(dev); 127 128 probe_pci_info(PCI_DEVICE(dev), errp); 129} 130 131static void pci_proxy_dev_exit(PCIDevice *pdev) 132{ 133 PCIProxyDev *dev = PCI_PROXY_DEV(pdev); 134 135 if (dev->ioc) { 136 qio_channel_close(dev->ioc, NULL); 137 } 138 139 migrate_del_blocker(dev->migration_blocker); 140 141 error_free(dev->migration_blocker); 142 143 proxy_memory_listener_deconfigure(&dev->proxy_listener); 144 145 event_notifier_cleanup(&dev->intr); 146 event_notifier_cleanup(&dev->resample); 147} 148 149static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val, 150 int len, unsigned int op) 151{ 152 MPQemuMsg msg = { 0 }; 153 uint64_t ret = -EINVAL; 154 Error *local_err = NULL; 155 156 msg.cmd = op; 157 msg.data.pci_conf_data.addr = addr; 158 msg.data.pci_conf_data.val = (op == MPQEMU_CMD_PCI_CFGWRITE) ? *val : 0; 159 msg.data.pci_conf_data.len = len; 160 msg.size = sizeof(PciConfDataMsg); 161 162 ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err); 163 if (local_err) { 164 error_report_err(local_err); 165 } 166 167 if (ret == UINT64_MAX) { 168 error_report("Failed to perform PCI config %s operation", 169 (op == MPQEMU_CMD_PCI_CFGREAD) ? "READ" : "WRITE"); 170 } 171 172 if (op == MPQEMU_CMD_PCI_CFGREAD) { 173 *val = (uint32_t)ret; 174 } 175} 176 177static uint32_t pci_proxy_read_config(PCIDevice *d, uint32_t addr, int len) 178{ 179 uint32_t val; 180 181 config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGREAD); 182 183 return val; 184} 185 186static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val, 187 int len) 188{ 189 /* 190 * Some of the functions access the copy of remote device's PCI config 191 * space which is cached in the proxy device. Therefore, maintain 192 * it updated. 193 */ 194 pci_default_write_config(d, addr, val, len); 195 196 config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGWRITE); 197} 198 199static Property proxy_properties[] = { 200 DEFINE_PROP_STRING("fd", PCIProxyDev, fd), 201 DEFINE_PROP_END_OF_LIST(), 202}; 203 204static void pci_proxy_dev_class_init(ObjectClass *klass, void *data) 205{ 206 DeviceClass *dc = DEVICE_CLASS(klass); 207 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 208 209 k->realize = pci_proxy_dev_realize; 210 k->exit = pci_proxy_dev_exit; 211 k->config_read = pci_proxy_read_config; 212 k->config_write = pci_proxy_write_config; 213 214 dc->reset = proxy_device_reset; 215 216 device_class_set_props(dc, proxy_properties); 217} 218 219static const TypeInfo pci_proxy_dev_type_info = { 220 .name = TYPE_PCI_PROXY_DEV, 221 .parent = TYPE_PCI_DEVICE, 222 .instance_size = sizeof(PCIProxyDev), 223 .class_init = pci_proxy_dev_class_init, 224 .interfaces = (InterfaceInfo[]) { 225 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 226 { }, 227 }, 228}; 229 230static void pci_proxy_dev_register_types(void) 231{ 232 type_register_static(&pci_proxy_dev_type_info); 233} 234 235type_init(pci_proxy_dev_register_types) 236 237static void send_bar_access_msg(PCIProxyDev *pdev, MemoryRegion *mr, 238 bool write, hwaddr addr, uint64_t *val, 239 unsigned size, bool memory) 240{ 241 MPQemuMsg msg = { 0 }; 242 long ret = -EINVAL; 243 Error *local_err = NULL; 244 245 msg.size = sizeof(BarAccessMsg); 246 msg.data.bar_access.addr = mr->addr + addr; 247 msg.data.bar_access.size = size; 248 msg.data.bar_access.memory = memory; 249 250 if (write) { 251 msg.cmd = MPQEMU_CMD_BAR_WRITE; 252 msg.data.bar_access.val = *val; 253 } else { 254 msg.cmd = MPQEMU_CMD_BAR_READ; 255 } 256 257 ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err); 258 if (local_err) { 259 error_report_err(local_err); 260 } 261 262 if (!write) { 263 *val = ret; 264 } 265} 266 267static void proxy_bar_write(void *opaque, hwaddr addr, uint64_t val, 268 unsigned size) 269{ 270 ProxyMemoryRegion *pmr = opaque; 271 272 send_bar_access_msg(pmr->dev, &pmr->mr, true, addr, &val, size, 273 pmr->memory); 274} 275 276static uint64_t proxy_bar_read(void *opaque, hwaddr addr, unsigned size) 277{ 278 ProxyMemoryRegion *pmr = opaque; 279 uint64_t val; 280 281 send_bar_access_msg(pmr->dev, &pmr->mr, false, addr, &val, size, 282 pmr->memory); 283 284 return val; 285} 286 287const MemoryRegionOps proxy_mr_ops = { 288 .read = proxy_bar_read, 289 .write = proxy_bar_write, 290 .endianness = DEVICE_NATIVE_ENDIAN, 291 .impl = { 292 .min_access_size = 1, 293 .max_access_size = 8, 294 }, 295}; 296 297static void probe_pci_info(PCIDevice *dev, Error **errp) 298{ 299 PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); 300 uint32_t orig_val, new_val, base_class, val; 301 PCIProxyDev *pdev = PCI_PROXY_DEV(dev); 302 DeviceClass *dc = DEVICE_CLASS(pc); 303 uint8_t type; 304 int i, size; 305 306 config_op_send(pdev, PCI_VENDOR_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD); 307 pc->vendor_id = (uint16_t)val; 308 309 config_op_send(pdev, PCI_DEVICE_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD); 310 pc->device_id = (uint16_t)val; 311 312 config_op_send(pdev, PCI_CLASS_DEVICE, &val, 2, MPQEMU_CMD_PCI_CFGREAD); 313 pc->class_id = (uint16_t)val; 314 315 config_op_send(pdev, PCI_SUBSYSTEM_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD); 316 pc->subsystem_id = (uint16_t)val; 317 318 base_class = pc->class_id >> 4; 319 switch (base_class) { 320 case PCI_BASE_CLASS_BRIDGE: 321 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 322 break; 323 case PCI_BASE_CLASS_STORAGE: 324 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 325 break; 326 case PCI_BASE_CLASS_NETWORK: 327 case PCI_BASE_CLASS_WIRELESS: 328 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 329 break; 330 case PCI_BASE_CLASS_INPUT: 331 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 332 break; 333 case PCI_BASE_CLASS_DISPLAY: 334 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); 335 break; 336 case PCI_BASE_CLASS_PROCESSOR: 337 set_bit(DEVICE_CATEGORY_CPU, dc->categories); 338 break; 339 default: 340 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 341 break; 342 } 343 344 for (i = 0; i < PCI_NUM_REGIONS; i++) { 345 config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4, 346 MPQEMU_CMD_PCI_CFGREAD); 347 new_val = 0xffffffff; 348 config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4, 349 MPQEMU_CMD_PCI_CFGWRITE); 350 config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4, 351 MPQEMU_CMD_PCI_CFGREAD); 352 size = (~(new_val & 0xFFFFFFF0)) + 1; 353 config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4, 354 MPQEMU_CMD_PCI_CFGWRITE); 355 type = (new_val & 0x1) ? 356 PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY; 357 358 if (size) { 359 g_autofree char *name = g_strdup_printf("bar-region-%d", i); 360 pdev->region[i].dev = pdev; 361 pdev->region[i].present = true; 362 if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) { 363 pdev->region[i].memory = true; 364 } 365 memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev), 366 &proxy_mr_ops, &pdev->region[i], 367 name, size); 368 pci_register_bar(dev, i, type, &pdev->region[i].mr); 369 } 370 } 371} 372 373static void proxy_device_reset(DeviceState *dev) 374{ 375 PCIProxyDev *pdev = PCI_PROXY_DEV(dev); 376 MPQemuMsg msg = { 0 }; 377 Error *local_err = NULL; 378 379 msg.cmd = MPQEMU_CMD_DEVICE_RESET; 380 msg.size = 0; 381 382 mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err); 383 if (local_err) { 384 error_report_err(local_err); 385 } 386 387}