pcie_pci_bridge.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * QEMU Generic PCIE-PCI Bridge
  3. *
  4. * Copyright (c) 2017 Aleksandr Bezzubikov
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "qapi/error.h"
  11. #include "qemu/module.h"
  12. #include "hw/pci/pci.h"
  13. #include "hw/pci/pci_bus.h"
  14. #include "hw/pci/pci_bridge.h"
  15. #include "hw/pci/msi.h"
  16. #include "hw/pci/shpc.h"
  17. #include "hw/pci/slotid_cap.h"
  18. #include "hw/qdev-properties.h"
  19. #include "qom/object.h"
  20. struct PCIEPCIBridge {
  21. /*< private >*/
  22. PCIBridge parent_obj;
  23. OnOffAuto msi;
  24. MemoryRegion shpc_bar;
  25. /*< public >*/
  26. };
  27. #define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
  28. OBJECT_DECLARE_SIMPLE_TYPE(PCIEPCIBridge, PCIE_PCI_BRIDGE_DEV)
  29. static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
  30. {
  31. PCIBridge *br = PCI_BRIDGE(d);
  32. PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
  33. int rc, pos;
  34. pci_bridge_initfn(d, TYPE_PCI_BUS);
  35. d->config[PCI_INTERRUPT_PIN] = 0x1;
  36. memory_region_init(&pcie_br->shpc_bar, OBJECT(d), "shpc-bar",
  37. shpc_bar_size(d));
  38. rc = shpc_init(d, &br->sec_bus, &pcie_br->shpc_bar, 0, errp);
  39. if (rc) {
  40. goto error;
  41. }
  42. rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
  43. if (rc < 0) {
  44. goto cap_error;
  45. }
  46. pos = pci_pm_init(d, 0, errp);
  47. if (pos < 0) {
  48. goto pm_error;
  49. }
  50. pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
  51. pcie_cap_arifwd_init(d);
  52. pcie_cap_deverr_init(d);
  53. rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
  54. if (rc < 0) {
  55. goto aer_error;
  56. }
  57. Error *local_err = NULL;
  58. if (pcie_br->msi != ON_OFF_AUTO_OFF) {
  59. rc = msi_init(d, 0, 1, true, true, &local_err);
  60. if (rc < 0) {
  61. assert(rc == -ENOTSUP);
  62. if (pcie_br->msi != ON_OFF_AUTO_ON) {
  63. error_free(local_err);
  64. } else {
  65. /* failed to satisfy user's explicit request for MSI */
  66. error_propagate(errp, local_err);
  67. goto msi_error;
  68. }
  69. }
  70. }
  71. pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
  72. PCI_BASE_ADDRESS_MEM_TYPE_64, &pcie_br->shpc_bar);
  73. return;
  74. msi_error:
  75. pcie_aer_exit(d);
  76. aer_error:
  77. pm_error:
  78. pcie_cap_exit(d);
  79. cap_error:
  80. shpc_cleanup(d, &pcie_br->shpc_bar);
  81. error:
  82. pci_bridge_exitfn(d);
  83. }
  84. static void pcie_pci_bridge_exit(PCIDevice *d)
  85. {
  86. PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
  87. pcie_cap_exit(d);
  88. shpc_cleanup(d, &bridge_dev->shpc_bar);
  89. pci_bridge_exitfn(d);
  90. }
  91. static void pcie_pci_bridge_reset(DeviceState *qdev)
  92. {
  93. PCIDevice *d = PCI_DEVICE(qdev);
  94. pci_bridge_reset(qdev);
  95. if (msi_present(d)) {
  96. msi_reset(d);
  97. }
  98. shpc_reset(d);
  99. }
  100. static void pcie_pci_bridge_write_config(PCIDevice *d,
  101. uint32_t address, uint32_t val, int len)
  102. {
  103. pci_bridge_write_config(d, address, val, len);
  104. if (msi_present(d)) {
  105. msi_write_config(d, address, val, len);
  106. }
  107. shpc_cap_write_config(d, address, val, len);
  108. }
  109. static const Property pcie_pci_bridge_dev_properties[] = {
  110. DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
  111. };
  112. static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
  113. .name = TYPE_PCIE_PCI_BRIDGE_DEV,
  114. .priority = MIG_PRI_PCI_BUS,
  115. .fields = (const VMStateField[]) {
  116. VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
  117. SHPC_VMSTATE(shpc, PCIDevice, NULL),
  118. VMSTATE_END_OF_LIST()
  119. }
  120. };
  121. static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data)
  122. {
  123. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  124. DeviceClass *dc = DEVICE_CLASS(klass);
  125. HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
  126. k->vendor_id = PCI_VENDOR_ID_REDHAT;
  127. k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE;
  128. k->realize = pcie_pci_bridge_realize;
  129. k->exit = pcie_pci_bridge_exit;
  130. k->config_write = pcie_pci_bridge_write_config;
  131. dc->vmsd = &pcie_pci_bridge_dev_vmstate;
  132. device_class_set_props(dc, pcie_pci_bridge_dev_properties);
  133. device_class_set_legacy_reset(dc, pcie_pci_bridge_reset);
  134. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  135. hc->plug = pci_bridge_dev_plug_cb;
  136. hc->unplug = pci_bridge_dev_unplug_cb;
  137. hc->unplug_request = pci_bridge_dev_unplug_request_cb;
  138. }
  139. static const TypeInfo pcie_pci_bridge_info = {
  140. .name = TYPE_PCIE_PCI_BRIDGE_DEV,
  141. .parent = TYPE_PCI_BRIDGE,
  142. .instance_size = sizeof(PCIEPCIBridge),
  143. .class_init = pcie_pci_bridge_class_init,
  144. .interfaces = (InterfaceInfo[]) {
  145. { TYPE_HOTPLUG_HANDLER },
  146. { INTERFACE_PCIE_DEVICE },
  147. { },
  148. }
  149. };
  150. static void pciepci_register(void)
  151. {
  152. type_register_static(&pcie_pci_bridge_info);
  153. }
  154. type_init(pciepci_register);