2
0

machine.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Machine for remote device
  3. *
  4. * This machine type is used by the remote device process in multi-process
  5. * QEMU. QEMU device models depend on parent busses, interrupt controllers,
  6. * memory regions, etc. The remote machine type offers this environment so
  7. * that QEMU device models can be used as remote devices.
  8. *
  9. * Copyright © 2018, 2021 Oracle and/or its affiliates.
  10. *
  11. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  12. * See the COPYING file in the top-level directory.
  13. *
  14. */
  15. #include "qemu/osdep.h"
  16. #include "hw/remote/machine.h"
  17. #include "exec/memory.h"
  18. #include "qapi/error.h"
  19. #include "hw/pci/pci_host.h"
  20. #include "hw/remote/iohub.h"
  21. #include "hw/remote/iommu.h"
  22. #include "hw/qdev-core.h"
  23. #include "hw/remote/vfio-user-obj.h"
  24. #include "hw/pci/msi.h"
  25. static void remote_machine_init(MachineState *machine)
  26. {
  27. MemoryRegion *system_memory, *system_io, *pci_memory;
  28. RemoteMachineState *s = REMOTE_MACHINE(machine);
  29. RemotePCIHost *rem_host;
  30. PCIHostState *pci_host;
  31. system_memory = get_system_memory();
  32. system_io = get_system_io();
  33. pci_memory = g_new(MemoryRegion, 1);
  34. memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
  35. rem_host = REMOTE_PCIHOST(qdev_new(TYPE_REMOTE_PCIHOST));
  36. rem_host->mr_pci_mem = pci_memory;
  37. rem_host->mr_sys_mem = system_memory;
  38. rem_host->mr_sys_io = system_io;
  39. s->host = rem_host;
  40. object_property_add_child(OBJECT(s), "remote-pcihost", OBJECT(rem_host));
  41. memory_region_add_subregion_overlap(system_memory, 0x0, pci_memory, -1);
  42. qdev_realize(DEVICE(rem_host), sysbus_get_default(), &error_fatal);
  43. pci_host = PCI_HOST_BRIDGE(rem_host);
  44. if (s->vfio_user) {
  45. remote_iommu_setup(pci_host->bus);
  46. msi_nonbroken = true;
  47. vfu_object_set_bus_irq(pci_host->bus);
  48. } else {
  49. remote_iohub_init(&s->iohub);
  50. pci_bus_irqs(pci_host->bus, remote_iohub_set_irq,
  51. &s->iohub, REMOTE_IOHUB_NB_PIRQS);
  52. pci_bus_map_irqs(pci_host->bus, remote_iohub_map_irq);
  53. }
  54. qbus_set_hotplug_handler(BUS(pci_host->bus), OBJECT(s));
  55. }
  56. static bool remote_machine_get_vfio_user(Object *obj, Error **errp)
  57. {
  58. RemoteMachineState *s = REMOTE_MACHINE(obj);
  59. return s->vfio_user;
  60. }
  61. static void remote_machine_set_vfio_user(Object *obj, bool value, Error **errp)
  62. {
  63. RemoteMachineState *s = REMOTE_MACHINE(obj);
  64. if (phase_check(PHASE_MACHINE_CREATED)) {
  65. error_setg(errp, "Error enabling vfio-user - machine already created");
  66. return;
  67. }
  68. s->vfio_user = value;
  69. }
  70. static bool remote_machine_get_auto_shutdown(Object *obj, Error **errp)
  71. {
  72. RemoteMachineState *s = REMOTE_MACHINE(obj);
  73. return s->auto_shutdown;
  74. }
  75. static void remote_machine_set_auto_shutdown(Object *obj, bool value,
  76. Error **errp)
  77. {
  78. RemoteMachineState *s = REMOTE_MACHINE(obj);
  79. s->auto_shutdown = value;
  80. }
  81. static void remote_machine_instance_init(Object *obj)
  82. {
  83. RemoteMachineState *s = REMOTE_MACHINE(obj);
  84. s->auto_shutdown = true;
  85. }
  86. static void remote_machine_dev_unplug_cb(HotplugHandler *hotplug_dev,
  87. DeviceState *dev, Error **errp)
  88. {
  89. qdev_unrealize(dev);
  90. if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
  91. remote_iommu_unplug_dev(PCI_DEVICE(dev));
  92. }
  93. }
  94. static void remote_machine_class_init(ObjectClass *oc, void *data)
  95. {
  96. MachineClass *mc = MACHINE_CLASS(oc);
  97. HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
  98. mc->init = remote_machine_init;
  99. mc->desc = "Experimental remote machine";
  100. hc->unplug = remote_machine_dev_unplug_cb;
  101. object_class_property_add_bool(oc, "vfio-user",
  102. remote_machine_get_vfio_user,
  103. remote_machine_set_vfio_user);
  104. object_class_property_add_bool(oc, "auto-shutdown",
  105. remote_machine_get_auto_shutdown,
  106. remote_machine_set_auto_shutdown);
  107. }
  108. static const TypeInfo remote_machine = {
  109. .name = TYPE_REMOTE_MACHINE,
  110. .parent = TYPE_MACHINE,
  111. .instance_size = sizeof(RemoteMachineState),
  112. .instance_init = remote_machine_instance_init,
  113. .class_init = remote_machine_class_init,
  114. .interfaces = (InterfaceInfo[]) {
  115. { TYPE_HOTPLUG_HANDLER },
  116. { }
  117. }
  118. };
  119. static void remote_machine_register_types(void)
  120. {
  121. type_register_static(&remote_machine);
  122. }
  123. type_init(remote_machine_register_types);