2
0

pcihp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * QEMU<->ACPI BIOS PCI hotplug interface
  3. *
  4. * QEMU supports PCI hotplug via ACPI. This module
  5. * implements the interface between QEMU and the ACPI BIOS.
  6. * Interface specification - see docs/specs/acpi_pci_hotplug.txt
  7. *
  8. * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
  9. * Copyright (c) 2006 Fabrice Bellard
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License version 2 as published by the Free Software Foundation.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, see <http://www.gnu.org/licenses/>
  22. *
  23. * Contributions after 2012-01-13 are licensed under the terms of the
  24. * GNU GPL, version 2 or (at your option) any later version.
  25. */
  26. #include "qemu/osdep.h"
  27. #include "hw/acpi/pcihp.h"
  28. #include "hw/pci-host/i440fx.h"
  29. #include "hw/pci/pci.h"
  30. #include "hw/pci/pci_bridge.h"
  31. #include "hw/acpi/acpi.h"
  32. #include "exec/address-spaces.h"
  33. #include "hw/pci/pci_bus.h"
  34. #include "migration/vmstate.h"
  35. #include "qapi/error.h"
  36. #include "qom/qom-qobject.h"
  37. #include "trace.h"
  38. #define ACPI_PCIHP_ADDR 0xae00
  39. #define ACPI_PCIHP_SIZE 0x0014
  40. #define PCI_UP_BASE 0x0000
  41. #define PCI_DOWN_BASE 0x0004
  42. #define PCI_EJ_BASE 0x0008
  43. #define PCI_RMV_BASE 0x000c
  44. #define PCI_SEL_BASE 0x0010
  45. typedef struct AcpiPciHpFind {
  46. int bsel;
  47. PCIBus *bus;
  48. } AcpiPciHpFind;
  49. static int acpi_pcihp_get_bsel(PCIBus *bus)
  50. {
  51. Error *local_err = NULL;
  52. uint64_t bsel = object_property_get_uint(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
  53. &local_err);
  54. if (local_err || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
  55. if (local_err) {
  56. error_free(local_err);
  57. }
  58. return -1;
  59. } else {
  60. return bsel;
  61. }
  62. }
  63. /* Assign BSEL property to all buses. In the future, this can be changed
  64. * to only assign to buses that support hotplug.
  65. */
  66. static void *acpi_set_bsel(PCIBus *bus, void *opaque)
  67. {
  68. unsigned *bsel_alloc = opaque;
  69. unsigned *bus_bsel;
  70. if (qbus_is_hotpluggable(BUS(bus))) {
  71. bus_bsel = g_malloc(sizeof *bus_bsel);
  72. *bus_bsel = (*bsel_alloc)++;
  73. object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
  74. bus_bsel, OBJ_PROP_FLAG_READ);
  75. }
  76. return bsel_alloc;
  77. }
  78. static void acpi_set_pci_info(void)
  79. {
  80. static bool bsel_is_set;
  81. PCIBus *bus;
  82. unsigned bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT;
  83. if (bsel_is_set) {
  84. return;
  85. }
  86. bsel_is_set = true;
  87. bus = find_i440fx(); /* TODO: Q35 support */
  88. if (bus) {
  89. /* Scan all PCI buses. Set property to enable acpi based hotplug. */
  90. pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);
  91. }
  92. }
  93. static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
  94. {
  95. AcpiPciHpFind *find = opaque;
  96. if (find->bsel == acpi_pcihp_get_bsel(bus)) {
  97. find->bus = bus;
  98. }
  99. }
  100. static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
  101. {
  102. AcpiPciHpFind find = { .bsel = bsel, .bus = NULL };
  103. if (bsel < 0) {
  104. return NULL;
  105. }
  106. pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find);
  107. /* Make bsel 0 eject root bus if bsel property is not set,
  108. * for compatibility with non acpi setups.
  109. * TODO: really needed?
  110. */
  111. if (!bsel && !find.bus) {
  112. find.bus = s->root;
  113. }
  114. return find.bus;
  115. }
  116. static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
  117. {
  118. PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
  119. DeviceClass *dc = DEVICE_GET_CLASS(dev);
  120. /*
  121. * ACPI doesn't allow hotplug of bridge devices. Don't allow
  122. * hot-unplug of bridge devices unless they were added by hotplug
  123. * (and so, not described by acpi).
  124. */
  125. return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable;
  126. }
  127. static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
  128. {
  129. HotplugHandler *hotplug_ctrl;
  130. BusChild *kid, *next;
  131. int slot = ctz32(slots);
  132. PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
  133. trace_acpi_pci_eject_slot(bsel, slot);
  134. if (!bus || slot > 31) {
  135. return;
  136. }
  137. /* Mark request as complete */
  138. s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
  139. s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot);
  140. QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
  141. DeviceState *qdev = kid->child;
  142. PCIDevice *dev = PCI_DEVICE(qdev);
  143. if (PCI_SLOT(dev->devfn) == slot) {
  144. if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
  145. hotplug_ctrl = qdev_get_hotplug_handler(qdev);
  146. hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
  147. object_unparent(OBJECT(qdev));
  148. }
  149. }
  150. }
  151. }
  152. static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
  153. {
  154. BusChild *kid, *next;
  155. PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
  156. /* Execute any pending removes during reset */
  157. while (s->acpi_pcihp_pci_status[bsel].down) {
  158. acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down);
  159. }
  160. s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
  161. if (!bus) {
  162. return;
  163. }
  164. QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
  165. DeviceState *qdev = kid->child;
  166. PCIDevice *pdev = PCI_DEVICE(qdev);
  167. int slot = PCI_SLOT(pdev->devfn);
  168. if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
  169. s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
  170. }
  171. }
  172. }
  173. static void acpi_pcihp_update(AcpiPciHpState *s)
  174. {
  175. int i;
  176. for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) {
  177. acpi_pcihp_update_hotplug_bus(s, i);
  178. }
  179. }
  180. void acpi_pcihp_reset(AcpiPciHpState *s)
  181. {
  182. acpi_set_pci_info();
  183. acpi_pcihp_update(s);
  184. }
  185. void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
  186. DeviceState *dev, Error **errp)
  187. {
  188. /* Only hotplugged devices need the hotplug capability. */
  189. if (dev->hotplugged &&
  190. acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))) < 0) {
  191. error_setg(errp, "Unsupported bus. Bus doesn't have property '"
  192. ACPI_PCIHP_PROP_BSEL "' set");
  193. return;
  194. }
  195. }
  196. void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
  197. DeviceState *dev, Error **errp)
  198. {
  199. PCIDevice *pdev = PCI_DEVICE(dev);
  200. int slot = PCI_SLOT(pdev->devfn);
  201. int bsel;
  202. /* Don't send event when device is enabled during qemu machine creation:
  203. * it is present on boot, no hotplug event is necessary. We do send an
  204. * event when the device is disabled later. */
  205. if (!dev->hotplugged) {
  206. /*
  207. * Overwrite the default hotplug handler with the ACPI PCI one
  208. * for cold plugged bridges only.
  209. */
  210. if (!s->legacy_piix &&
  211. object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
  212. PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
  213. qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev));
  214. /* We don't have to overwrite any other hotplug handler yet */
  215. assert(QLIST_EMPTY(&sec->child));
  216. }
  217. return;
  218. }
  219. bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
  220. g_assert(bsel >= 0);
  221. s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
  222. acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
  223. }
  224. void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
  225. DeviceState *dev, Error **errp)
  226. {
  227. trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
  228. acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
  229. qdev_unrealize(dev);
  230. }
  231. void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
  232. AcpiPciHpState *s, DeviceState *dev,
  233. Error **errp)
  234. {
  235. PCIDevice *pdev = PCI_DEVICE(dev);
  236. int slot = PCI_SLOT(pdev->devfn);
  237. int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
  238. trace_acpi_pci_unplug_request(bsel, slot);
  239. if (bsel < 0) {
  240. error_setg(errp, "Unsupported bus. Bus doesn't have property '"
  241. ACPI_PCIHP_PROP_BSEL "' set");
  242. return;
  243. }
  244. s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
  245. acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
  246. }
  247. static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
  248. {
  249. AcpiPciHpState *s = opaque;
  250. uint32_t val = 0;
  251. int bsel = s->hotplug_select;
  252. if (bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
  253. return 0;
  254. }
  255. switch (addr) {
  256. case PCI_UP_BASE:
  257. val = s->acpi_pcihp_pci_status[bsel].up;
  258. if (!s->legacy_piix) {
  259. s->acpi_pcihp_pci_status[bsel].up = 0;
  260. }
  261. trace_acpi_pci_up_read(val);
  262. break;
  263. case PCI_DOWN_BASE:
  264. val = s->acpi_pcihp_pci_status[bsel].down;
  265. trace_acpi_pci_down_read(val);
  266. break;
  267. case PCI_EJ_BASE:
  268. /* No feature defined yet */
  269. trace_acpi_pci_features_read(val);
  270. break;
  271. case PCI_RMV_BASE:
  272. val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
  273. trace_acpi_pci_rmv_read(val);
  274. break;
  275. case PCI_SEL_BASE:
  276. val = s->hotplug_select;
  277. trace_acpi_pci_sel_read(val);
  278. default:
  279. break;
  280. }
  281. return val;
  282. }
  283. static void pci_write(void *opaque, hwaddr addr, uint64_t data,
  284. unsigned int size)
  285. {
  286. AcpiPciHpState *s = opaque;
  287. switch (addr) {
  288. case PCI_EJ_BASE:
  289. if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
  290. break;
  291. }
  292. acpi_pcihp_eject_slot(s, s->hotplug_select, data);
  293. trace_acpi_pci_ej_write(addr, data);
  294. break;
  295. case PCI_SEL_BASE:
  296. s->hotplug_select = s->legacy_piix ? ACPI_PCIHP_BSEL_DEFAULT : data;
  297. trace_acpi_pci_sel_write(addr, data);
  298. default:
  299. break;
  300. }
  301. }
  302. static const MemoryRegionOps acpi_pcihp_io_ops = {
  303. .read = pci_read,
  304. .write = pci_write,
  305. .endianness = DEVICE_LITTLE_ENDIAN,
  306. .valid = {
  307. .min_access_size = 4,
  308. .max_access_size = 4,
  309. },
  310. };
  311. void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
  312. MemoryRegion *address_space_io, bool bridges_enabled)
  313. {
  314. s->io_len = ACPI_PCIHP_SIZE;
  315. s->io_base = ACPI_PCIHP_ADDR;
  316. s->root= root_bus;
  317. s->legacy_piix = !bridges_enabled;
  318. memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s,
  319. "acpi-pci-hotplug", s->io_len);
  320. memory_region_add_subregion(address_space_io, s->io_base, &s->io);
  321. object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base,
  322. OBJ_PROP_FLAG_READ);
  323. object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len,
  324. OBJ_PROP_FLAG_READ);
  325. }
  326. const VMStateDescription vmstate_acpi_pcihp_pci_status = {
  327. .name = "acpi_pcihp_pci_status",
  328. .version_id = 1,
  329. .minimum_version_id = 1,
  330. .fields = (VMStateField[]) {
  331. VMSTATE_UINT32(up, AcpiPciHpPciStatus),
  332. VMSTATE_UINT32(down, AcpiPciHpPciStatus),
  333. VMSTATE_END_OF_LIST()
  334. }
  335. };