pcihp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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_disable_root_bus(void)
  94. {
  95. static bool root_hp_disabled;
  96. PCIBus *bus;
  97. if (root_hp_disabled) {
  98. return;
  99. }
  100. bus = find_i440fx();
  101. if (bus) {
  102. /* setting the hotplug handler to NULL makes the bus non-hotpluggable */
  103. qbus_set_hotplug_handler(BUS(bus), NULL);
  104. }
  105. root_hp_disabled = true;
  106. return;
  107. }
  108. static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
  109. {
  110. AcpiPciHpFind *find = opaque;
  111. if (find->bsel == acpi_pcihp_get_bsel(bus)) {
  112. find->bus = bus;
  113. }
  114. }
  115. static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
  116. {
  117. AcpiPciHpFind find = { .bsel = bsel, .bus = NULL };
  118. if (bsel < 0) {
  119. return NULL;
  120. }
  121. pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find);
  122. /* Make bsel 0 eject root bus if bsel property is not set,
  123. * for compatibility with non acpi setups.
  124. * TODO: really needed?
  125. */
  126. if (!bsel && !find.bus) {
  127. find.bus = s->root;
  128. }
  129. /*
  130. * Check if find.bus is actually hotpluggable. If bsel is set to
  131. * NULL for example on the root bus in order to make it
  132. * non-hotpluggable, find.bus will match the root bus when bsel
  133. * is 0. See acpi_pcihp_test_hotplug_bus() above. Since the
  134. * bus is not hotpluggable however, we should not select the bus.
  135. * Instead, we should set find.bus to NULL in that case. In the check
  136. * below, we generalize this case for all buses, not just the root bus.
  137. * The callers of this function check for a null return value and
  138. * handle them appropriately.
  139. */
  140. if (find.bus && !qbus_is_hotpluggable(BUS(find.bus))) {
  141. find.bus = NULL;
  142. }
  143. return find.bus;
  144. }
  145. static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
  146. {
  147. PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
  148. DeviceClass *dc = DEVICE_GET_CLASS(dev);
  149. /*
  150. * ACPI doesn't allow hotplug of bridge devices. Don't allow
  151. * hot-unplug of bridge devices unless they were added by hotplug
  152. * (and so, not described by acpi).
  153. */
  154. return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable;
  155. }
  156. static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
  157. {
  158. HotplugHandler *hotplug_ctrl;
  159. BusChild *kid, *next;
  160. int slot = ctz32(slots);
  161. PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
  162. trace_acpi_pci_eject_slot(bsel, slot);
  163. if (!bus || slot > 31) {
  164. return;
  165. }
  166. /* Mark request as complete */
  167. s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
  168. s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot);
  169. QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
  170. DeviceState *qdev = kid->child;
  171. PCIDevice *dev = PCI_DEVICE(qdev);
  172. if (PCI_SLOT(dev->devfn) == slot) {
  173. if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
  174. hotplug_ctrl = qdev_get_hotplug_handler(qdev);
  175. hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
  176. object_unparent(OBJECT(qdev));
  177. }
  178. }
  179. }
  180. }
  181. static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
  182. {
  183. BusChild *kid, *next;
  184. PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
  185. /* Execute any pending removes during reset */
  186. while (s->acpi_pcihp_pci_status[bsel].down) {
  187. acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down);
  188. }
  189. s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
  190. if (!bus) {
  191. return;
  192. }
  193. QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
  194. DeviceState *qdev = kid->child;
  195. PCIDevice *pdev = PCI_DEVICE(qdev);
  196. int slot = PCI_SLOT(pdev->devfn);
  197. if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
  198. s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
  199. }
  200. }
  201. }
  202. static void acpi_pcihp_update(AcpiPciHpState *s)
  203. {
  204. int i;
  205. for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) {
  206. acpi_pcihp_update_hotplug_bus(s, i);
  207. }
  208. }
  209. void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off)
  210. {
  211. if (acpihp_root_off) {
  212. acpi_pcihp_disable_root_bus();
  213. }
  214. acpi_set_pci_info();
  215. acpi_pcihp_update(s);
  216. }
  217. void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
  218. DeviceState *dev, Error **errp)
  219. {
  220. /* Only hotplugged devices need the hotplug capability. */
  221. if (dev->hotplugged &&
  222. acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))) < 0) {
  223. error_setg(errp, "Unsupported bus. Bus doesn't have property '"
  224. ACPI_PCIHP_PROP_BSEL "' set");
  225. return;
  226. }
  227. }
  228. void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
  229. DeviceState *dev, Error **errp)
  230. {
  231. PCIDevice *pdev = PCI_DEVICE(dev);
  232. int slot = PCI_SLOT(pdev->devfn);
  233. int bsel;
  234. /* Don't send event when device is enabled during qemu machine creation:
  235. * it is present on boot, no hotplug event is necessary. We do send an
  236. * event when the device is disabled later. */
  237. if (!dev->hotplugged) {
  238. /*
  239. * Overwrite the default hotplug handler with the ACPI PCI one
  240. * for cold plugged bridges only.
  241. */
  242. if (!s->legacy_piix &&
  243. object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
  244. PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
  245. qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev));
  246. /* We don't have to overwrite any other hotplug handler yet */
  247. assert(QLIST_EMPTY(&sec->child));
  248. }
  249. return;
  250. }
  251. bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
  252. g_assert(bsel >= 0);
  253. s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
  254. acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
  255. }
  256. void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
  257. DeviceState *dev, Error **errp)
  258. {
  259. trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
  260. acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
  261. qdev_unrealize(dev);
  262. }
  263. void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
  264. AcpiPciHpState *s, DeviceState *dev,
  265. Error **errp)
  266. {
  267. PCIDevice *pdev = PCI_DEVICE(dev);
  268. int slot = PCI_SLOT(pdev->devfn);
  269. int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
  270. trace_acpi_pci_unplug_request(bsel, slot);
  271. if (bsel < 0) {
  272. error_setg(errp, "Unsupported bus. Bus doesn't have property '"
  273. ACPI_PCIHP_PROP_BSEL "' set");
  274. return;
  275. }
  276. s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
  277. acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
  278. }
  279. static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
  280. {
  281. AcpiPciHpState *s = opaque;
  282. uint32_t val = 0;
  283. int bsel = s->hotplug_select;
  284. if (bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
  285. return 0;
  286. }
  287. switch (addr) {
  288. case PCI_UP_BASE:
  289. val = s->acpi_pcihp_pci_status[bsel].up;
  290. if (!s->legacy_piix) {
  291. s->acpi_pcihp_pci_status[bsel].up = 0;
  292. }
  293. trace_acpi_pci_up_read(val);
  294. break;
  295. case PCI_DOWN_BASE:
  296. val = s->acpi_pcihp_pci_status[bsel].down;
  297. trace_acpi_pci_down_read(val);
  298. break;
  299. case PCI_EJ_BASE:
  300. /* No feature defined yet */
  301. trace_acpi_pci_features_read(val);
  302. break;
  303. case PCI_RMV_BASE:
  304. val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
  305. trace_acpi_pci_rmv_read(val);
  306. break;
  307. case PCI_SEL_BASE:
  308. val = s->hotplug_select;
  309. trace_acpi_pci_sel_read(val);
  310. default:
  311. break;
  312. }
  313. return val;
  314. }
  315. static void pci_write(void *opaque, hwaddr addr, uint64_t data,
  316. unsigned int size)
  317. {
  318. AcpiPciHpState *s = opaque;
  319. switch (addr) {
  320. case PCI_EJ_BASE:
  321. if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
  322. break;
  323. }
  324. acpi_pcihp_eject_slot(s, s->hotplug_select, data);
  325. trace_acpi_pci_ej_write(addr, data);
  326. break;
  327. case PCI_SEL_BASE:
  328. s->hotplug_select = s->legacy_piix ? ACPI_PCIHP_BSEL_DEFAULT : data;
  329. trace_acpi_pci_sel_write(addr, data);
  330. default:
  331. break;
  332. }
  333. }
  334. static const MemoryRegionOps acpi_pcihp_io_ops = {
  335. .read = pci_read,
  336. .write = pci_write,
  337. .endianness = DEVICE_LITTLE_ENDIAN,
  338. .valid = {
  339. .min_access_size = 4,
  340. .max_access_size = 4,
  341. },
  342. };
  343. void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
  344. MemoryRegion *address_space_io, bool bridges_enabled)
  345. {
  346. s->io_len = ACPI_PCIHP_SIZE;
  347. s->io_base = ACPI_PCIHP_ADDR;
  348. s->root= root_bus;
  349. s->legacy_piix = !bridges_enabled;
  350. memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s,
  351. "acpi-pci-hotplug", s->io_len);
  352. memory_region_add_subregion(address_space_io, s->io_base, &s->io);
  353. object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base,
  354. OBJ_PROP_FLAG_READ);
  355. object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len,
  356. OBJ_PROP_FLAG_READ);
  357. }
  358. const VMStateDescription vmstate_acpi_pcihp_pci_status = {
  359. .name = "acpi_pcihp_pci_status",
  360. .version_id = 1,
  361. .minimum_version_id = 1,
  362. .fields = (VMStateField[]) {
  363. VMSTATE_UINT32(up, AcpiPciHpPciStatus),
  364. VMSTATE_UINT32(down, AcpiPciHpPciStatus),
  365. VMSTATE_END_OF_LIST()
  366. }
  367. };