master
c 933 lines 29.8 KB
Raw
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.rst
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.1 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
27 #include "qemu/osdep.h"
28 #include "hw/acpi/pcihp.h"
29 #include "hw/acpi/aml-build.h"
30 #include "hw/acpi/acpi_aml_interface.h"
31 #include "hw/pci-host/i440fx.h"
32 #include "hw/pci/pci.h"
33 #include "hw/pci/pci_bridge.h"
34 #include "hw/pci/pci_host.h"
35 #include "hw/pci/pcie_port.h"
36 #include "hw/pci-bridge/xio3130_downstream.h"
37 #include "hw/i386/acpi-build.h"
38 #include "hw/acpi/acpi.h"
39 #include "hw/pci/pci_bus.h"
40 #include "migration/vmstate.h"
41 #include "qapi/error.h"
42 #include "qom/qom-qobject.h"
43 #include "qobject/qnum.h"
44 #include "trace.h"
45
46 #define PCI_UP_BASE 0x0000
47 #define PCI_DOWN_BASE 0x0004
48 #define PCI_EJ_BASE 0x0008
49 #define PCI_RMV_BASE 0x000c
50 #define PCI_SEL_BASE 0x0010
51 #define PCI_AIDX_BASE 0x0014
52
53 typedef struct AcpiPciHpFind {
54 int bsel;
55 PCIBus *bus;
56 } AcpiPciHpFind;
57
58 static int acpi_pcihp_get_bsel(PCIBus *bus)
59 {
60 Error *local_err = NULL;
61 uint32_t bsel = object_property_get_uint(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
62 &local_err);
63
64 if (local_err || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
65 error_free(local_err);
66 return -1;
67 } else {
68 return bsel;
69 }
70 }
71
72 typedef struct {
73 unsigned bsel_alloc;
74 bool has_bridge_hotplug;
75 } BSELInfo;
76
77 /* Assign BSEL property only to buses that support hotplug. */
78 static void *acpi_set_bsel(PCIBus *bus, void *opaque)
79 {
80 BSELInfo *info = opaque;
81 DeviceState *br = bus->qbus.parent;
82 bool is_bridge = IS_PCI_BRIDGE(br);
83
84 /* hotplugged bridges can't be described in ACPI ignore them */
85 if (qbus_is_hotpluggable(BUS(bus))) {
86 if (!is_bridge || (!br->hotplugged && info->has_bridge_hotplug)) {
87 object_property_set_uint(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
88 info->bsel_alloc++, NULL);
89 }
90 }
91
92 return info;
93 }
94
95 static void acpi_set_pci_info(AcpiPciHpState *s)
96 {
97 static bool bsel_is_set;
98 bool has_bridge_hotplug = s->use_acpi_hotplug_bridge;
99 PCIBus *bus;
100 BSELInfo info = { .bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT,
101 .has_bridge_hotplug = has_bridge_hotplug };
102
103 if (bsel_is_set) {
104 return;
105 }
106 bsel_is_set = true;
107
108
109 bus = s->root;
110 if (bus) {
111 /* Scan all PCI buses. Set property to enable acpi based hotplug. */
112 pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &info);
113 }
114 }
115
116 static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
117 {
118 AcpiPciHpFind *find = opaque;
119 if (find->bsel == acpi_pcihp_get_bsel(bus)) {
120 find->bus = bus;
121 }
122 }
123
124 static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
125 {
126 AcpiPciHpFind find = { .bsel = bsel, .bus = NULL };
127
128 if (bsel < 0) {
129 return NULL;
130 }
131
132 pci_for_each_bus(s->root, acpi_pcihp_test_hotplug_bus, &find);
133
134 /* Make bsel 0 eject root bus if bsel property is not set,
135 * for compatibility with non acpi setups.
136 * TODO: really needed?
137 */
138 if (!bsel && !find.bus) {
139 find.bus = s->root;
140 }
141
142 /*
143 * Check if find.bus is actually hotpluggable. If bsel is set to
144 * NULL for example on the root bus in order to make it
145 * non-hotpluggable, find.bus will match the root bus when bsel
146 * is 0. See acpi_pcihp_test_hotplug_bus() above. Since the
147 * bus is not hotpluggable however, we should not select the bus.
148 * Instead, we should set find.bus to NULL in that case. In the check
149 * below, we generalize this case for all buses, not just the root bus.
150 * The callers of this function check for a null return value and
151 * handle them appropriately.
152 */
153 if (find.bus && !qbus_is_hotpluggable(BUS(find.bus))) {
154 find.bus = NULL;
155 }
156 return find.bus;
157 }
158
159 static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
160 {
161 DeviceClass *dc = DEVICE_GET_CLASS(dev);
162 /*
163 * ACPI doesn't allow hotplug of bridge devices. Don't allow
164 * hot-unplug of bridge devices unless they were added by hotplug
165 * (and so, not described by acpi).
166 *
167 * Don't allow hot-unplug of SR-IOV Virtual Functions, as they
168 * will be removed implicitly, when Physical Function is unplugged.
169 */
170 return (IS_PCI_BRIDGE(dev) && !dev->qdev.hotplugged) || !dc->hotpluggable ||
171 pci_is_vf(dev);
172 }
173
174 static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
175 {
176 HotplugHandler *hotplug_ctrl;
177 BusChild *kid, *next;
178 int slot = ctz32(slots);
179 PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
180
181 trace_acpi_pci_eject_slot(bsel, slot);
182
183 if (!bus || slot > 31) {
184 return;
185 }
186
187 /* Mark request as complete */
188 s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
189 s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot);
190
191 QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
192 DeviceState *qdev = kid->child;
193 PCIDevice *dev = PCI_DEVICE(qdev);
194 if (PCI_SLOT(dev->devfn) == slot) {
195 if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
196 /*
197 * partially_hotplugged is used by virtio-net failover:
198 * failover has asked the guest OS to unplug the device
199 * but we need to keep some references to the device
200 * to be able to plug it back in case of failure so
201 * we don't execute hotplug_handler_unplug().
202 */
203 if (dev->partially_hotplugged) {
204 /*
205 * pending_deleted_event is set to true when
206 * virtio-net failover asks to unplug the device,
207 * and set to false here when the operation is done
208 * This is used by the migration loop to detect the
209 * end of the operation and really start the migration.
210 */
211 qdev->pending_deleted_event = false;
212 } else {
213 hotplug_ctrl = qdev_get_hotplug_handler(qdev);
214 hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
215 object_unparent(OBJECT(qdev));
216 }
217 }
218 }
219 }
220 }
221
222 static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
223 {
224 BusChild *kid, *next;
225 PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
226
227 /* Execute any pending removes during reset */
228 while (s->acpi_pcihp_pci_status[bsel].down) {
229 acpi_pcihp_eject_slot(s, bsel, s->acpi_pcihp_pci_status[bsel].down);
230 }
231
232 s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
233
234 if (!bus) {
235 return;
236 }
237 QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
238 DeviceState *qdev = kid->child;
239 PCIDevice *pdev = PCI_DEVICE(qdev);
240 int slot = PCI_SLOT(pdev->devfn);
241
242 if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
243 s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
244 }
245 }
246 }
247
248 static void acpi_pcihp_update(AcpiPciHpState *s)
249 {
250 int i;
251
252 for (i = 0; i < ACPI_PCIHP_MAX_HOTPLUG_BUS; ++i) {
253 acpi_pcihp_update_hotplug_bus(s, i);
254 }
255 }
256
257 void acpi_pcihp_reset(AcpiPciHpState *s)
258 {
259 acpi_set_pci_info(s);
260 acpi_pcihp_update(s);
261 }
262
263 void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
264 DeviceState *dev, Error **errp)
265 {
266 PCIDevice *pdev = PCI_DEVICE(dev);
267
268 /* Only hotplugged devices need the hotplug capability. */
269 if (dev->hotplugged &&
270 acpi_pcihp_get_bsel(pci_get_bus(pdev)) < 0) {
271 error_setg(errp, "Unsupported bus. Bus doesn't have property '"
272 ACPI_PCIHP_PROP_BSEL "' set");
273 return;
274 }
275 }
276
277 void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
278 DeviceState *dev, Error **errp)
279 {
280 PCIDevice *pdev = PCI_DEVICE(dev);
281 int slot = PCI_SLOT(pdev->devfn);
282 PCIDevice *bridge;
283 PCIBus *bus;
284 int bsel;
285
286 /* Don't send event when device is enabled during qemu machine creation:
287 * it is present on boot, no hotplug event is necessary. We do send an
288 * event when the device is disabled later. */
289 if (!dev->hotplugged) {
290 /*
291 * Overwrite the default hotplug handler with the ACPI PCI one
292 * for cold plugged bridges only.
293 */
294 if (s->use_acpi_hotplug_bridge &&
295 object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
296 PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
297
298 qbus_set_hotplug_handler(BUS(sec), OBJECT(hotplug_dev));
299 /* We don't have to overwrite any other hotplug handler yet */
300 assert(QLIST_EMPTY(&sec->child));
301 }
302
303 return;
304 }
305
306 bus = pci_get_bus(pdev);
307 bridge = pci_bridge_get_device(bus);
308 if (object_dynamic_cast(OBJECT(bridge), TYPE_PCIE_ROOT_PORT) ||
309 object_dynamic_cast(OBJECT(bridge), TYPE_XIO3130_DOWNSTREAM)) {
310 pcie_cap_slot_enable_power(bridge);
311 }
312
313 bsel = acpi_pcihp_get_bsel(bus);
314 g_assert(bsel >= 0);
315 s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
316 acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
317 }
318
319 void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
320 DeviceState *dev, Error **errp)
321 {
322 PCIDevice *pdev = PCI_DEVICE(dev);
323
324 trace_acpi_pci_unplug(PCI_SLOT(pdev->devfn),
325 acpi_pcihp_get_bsel(pci_get_bus(pdev)));
326
327 qdev_unrealize(dev);
328 }
329
330 void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
331 AcpiPciHpState *s, DeviceState *dev,
332 Error **errp)
333 {
334 PCIDevice *pdev = PCI_DEVICE(dev);
335 int slot = PCI_SLOT(pdev->devfn);
336 int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
337
338 trace_acpi_pci_unplug_request(bsel, slot);
339
340 if (bsel < 0) {
341 error_setg(errp, "Unsupported bus. Bus doesn't have property '"
342 ACPI_PCIHP_PROP_BSEL "' set");
343 return;
344 }
345
346 /*
347 * pending_deleted_event is used by virtio-net failover to detect the
348 * end of the unplug operation, the flag is set to false in
349 * acpi_pcihp_eject_slot() when the operation is completed.
350 */
351 pdev->qdev.pending_deleted_event = true;
352 /* if unplug was requested before OSPM is initialized,
353 * linux kernel will clear GPE0.sts[] bits during boot, which effectively
354 * hides unplug event. And than followup qmp_device_del() calls remain
355 * blocked by above flag permanently.
356 * Unblock qmp_device_del() by setting expire limit, so user can
357 * repeat unplug request later when OSPM has been booted.
358 */
359 pdev->qdev.pending_deleted_expires_ms =
360 qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); /* 1 msec */
361
362 s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
363 acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
364 }
365
366 bool acpi_pcihp_is_hotpluggable_bus(AcpiPciHpState *s, BusState *bus)
367 {
368 Object *o = OBJECT(bus->parent);
369
370 if (s->use_acpi_hotplug_bridge &&
371 object_dynamic_cast(o, TYPE_PCI_BRIDGE)) {
372 if (object_dynamic_cast(o, TYPE_PCIE_SLOT) && !PCIE_SLOT(o)->hotplug) {
373 return false;
374 }
375 return true;
376 }
377
378 if (s->use_acpi_root_pci_hotplug) {
379 return true;
380 }
381 return false;
382 }
383
384 static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
385 {
386 AcpiPciHpState *s = opaque;
387 uint32_t val = 0;
388 int bsel = s->hotplug_select;
389
390 if (bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
391 return 0;
392 }
393
394 switch (addr) {
395 case PCI_UP_BASE:
396 val = s->acpi_pcihp_pci_status[bsel].up;
397 if (s->use_acpi_hotplug_bridge) {
398 s->acpi_pcihp_pci_status[bsel].up = 0;
399 }
400 trace_acpi_pci_up_read(val);
401 break;
402 case PCI_DOWN_BASE:
403 val = s->acpi_pcihp_pci_status[bsel].down;
404 trace_acpi_pci_down_read(val);
405 break;
406 case PCI_EJ_BASE:
407 trace_acpi_pci_features_read(val);
408 break;
409 case PCI_RMV_BASE:
410 val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
411 trace_acpi_pci_rmv_read(val);
412 break;
413 case PCI_SEL_BASE:
414 val = s->hotplug_select;
415 trace_acpi_pci_sel_read(val);
416 break;
417 case PCI_AIDX_BASE:
418 val = s->acpi_index;
419 s->acpi_index = 0;
420 trace_acpi_pci_acpi_index_read(val);
421 break;
422 default:
423 break;
424 }
425
426 return val;
427 }
428
429 static void pci_write(void *opaque, hwaddr addr, uint64_t data,
430 unsigned int size)
431 {
432 int slot;
433 PCIBus *bus;
434 BusChild *kid, *next;
435 AcpiPciHpState *s = opaque;
436
437 s->acpi_index = 0;
438 switch (addr) {
439 case PCI_AIDX_BASE:
440 /*
441 * fetch acpi-index for specified slot so that follow up read from
442 * PCI_AIDX_BASE can return it to guest
443 */
444 slot = ctz32(data);
445
446 if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
447 break;
448 }
449
450 bus = acpi_pcihp_find_hotplug_bus(s, s->hotplug_select);
451 if (!bus) {
452 break;
453 }
454 QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
455 Object *o = OBJECT(kid->child);
456 PCIDevice *dev = PCI_DEVICE(o);
457 if (PCI_SLOT(dev->devfn) == slot) {
458 s->acpi_index = object_property_get_uint(o, "acpi-index", NULL);
459 break;
460 }
461 }
462 trace_acpi_pci_acpi_index_write(s->hotplug_select, slot, s->acpi_index);
463 break;
464 case PCI_EJ_BASE:
465 if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
466 break;
467 }
468 acpi_pcihp_eject_slot(s, s->hotplug_select, data);
469 trace_acpi_pci_ej_write(addr, data);
470 break;
471 case PCI_SEL_BASE:
472 s->hotplug_select = s->use_acpi_hotplug_bridge ? data :
473 ACPI_PCIHP_BSEL_DEFAULT;
474 trace_acpi_pci_sel_write(addr, data);
475 default:
476 break;
477 }
478 }
479
480 static const MemoryRegionOps acpi_pcihp_io_ops = {
481 .read = pci_read,
482 .write = pci_write,
483 .endianness = DEVICE_LITTLE_ENDIAN,
484 .valid = {
485 .min_access_size = 4,
486 .max_access_size = 4,
487 },
488 };
489
490 void acpi_pcihp_init(Object *owner, AcpiPciHpState *s,
491 MemoryRegion *io, uint16_t io_base)
492 {
493 s->io_len = ACPI_PCIHP_SIZE;
494 s->io_base = io_base;
495
496 assert(s->root);
497
498 memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s,
499 "acpi-pci-hotplug", s->io_len);
500 memory_region_add_subregion(io, s->io_base, &s->io);
501 }
502
503 void build_append_pci_dsm_func0_common(Aml *ctx, Aml *retvar)
504 {
505 Aml *UUID, *ifctx1;
506 uint8_t byte_list[1] = { 0 }; /* nothing supported yet */
507
508 aml_append(ctx, aml_store(aml_buffer(1, byte_list), retvar));
509 /*
510 * PCI Firmware Specification 3.1
511 * 4.6. _DSM Definitions for PCI
512 */
513 UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D");
514 ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(0), UUID)));
515 {
516 /* call is for unsupported UUID, bail out */
517 aml_append(ifctx1, aml_return(retvar));
518 }
519 aml_append(ctx, ifctx1);
520
521 ifctx1 = aml_if(aml_lless(aml_arg(1), aml_int(2)));
522 {
523 /* call is for unsupported REV, bail out */
524 aml_append(ifctx1, aml_return(retvar));
525 }
526 aml_append(ctx, ifctx1);
527 }
528
529 static Aml *aml_pci_pdsm(void)
530 {
531 Aml *method, *ifctx, *ifctx1;
532 Aml *ret = aml_local(0);
533 Aml *caps = aml_local(1);
534 Aml *acpi_index = aml_local(2);
535 Aml *zero = aml_int(0);
536 Aml *one = aml_int(1);
537 Aml *not_supp = aml_int(0xFFFFFFFF);
538 Aml *func = aml_arg(2);
539 Aml *params = aml_arg(4);
540 Aml *bnum = aml_derefof(aml_index(params, aml_int(0)));
541 Aml *sunum = aml_derefof(aml_index(params, aml_int(1)));
542
543 method = aml_method("PDSM", 5, AML_SERIALIZED);
544
545 /* get supported functions */
546 ifctx = aml_if(aml_equal(func, zero));
547 {
548 build_append_pci_dsm_func0_common(ifctx, ret);
549
550 aml_append(ifctx, aml_store(zero, caps));
551 aml_append(ifctx,
552 aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
553 /*
554 * advertise function 7 if device has acpi-index
555 * acpi_index values:
556 * 0: not present (default value)
557 * FFFFFFFF: not supported (old QEMU without PIDX reg)
558 * other: device's acpi-index
559 */
560 ifctx1 = aml_if(aml_lnot(
561 aml_or(aml_equal(acpi_index, zero),
562 aml_equal(acpi_index, not_supp), NULL)
563 ));
564 {
565 /* have supported functions */
566 aml_append(ifctx1, aml_or(caps, one, caps));
567 /* support for function 7 */
568 aml_append(ifctx1,
569 aml_or(caps, aml_shiftleft(one, aml_int(7)), caps));
570 }
571 aml_append(ifctx, ifctx1);
572
573 aml_append(ifctx, aml_store(caps, aml_index(ret, zero)));
574 aml_append(ifctx, aml_return(ret));
575 }
576 aml_append(method, ifctx);
577
578 /* handle specific functions requests */
579 /*
580 * PCI Firmware Specification 3.1
581 * 4.6.7. _DSM for Naming a PCI or PCI Express Device Under
582 * Operating Systems
583 */
584 ifctx = aml_if(aml_equal(func, aml_int(7)));
585 {
586 Aml *pkg = aml_package(2);
587
588 aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
589 aml_append(ifctx, aml_store(pkg, ret));
590 /*
591 * Windows calls func=7 without checking if it's available,
592 * as workaround Microsoft has suggested to return invalid for func7
593 * Package, so return 2 elements package but only initialize elements
594 * when acpi_index is supported and leave them uninitialized, which
595 * leads elements to being Uninitialized ObjectType and should trip
596 * Windows into discarding result as an unexpected and prevent setting
597 * bogus 'PCI Label' on the device.
598 */
599 ifctx1 = aml_if(aml_lnot(aml_lor(
600 aml_equal(acpi_index, zero), aml_equal(acpi_index, not_supp)
601 )));
602 {
603 aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
604 /*
605 * optional, if not impl. should return null string
606 */
607 aml_append(ifctx1, aml_store(aml_string("%s", ""),
608 aml_index(ret, one)));
609 }
610 aml_append(ifctx, ifctx1);
611
612 aml_append(ifctx, aml_return(ret));
613 }
614
615 aml_append(method, ifctx);
616 return method;
617 }
618
619 void build_acpi_pci_hotplug(Aml *table, AmlRegionSpace rs, uint64_t pcihp_addr)
620 {
621 Aml *scope;
622 Aml *field;
623 Aml *method;
624
625 scope = aml_scope("_SB.PCI0");
626
627 aml_append(scope,
628 aml_operation_region("PCST", rs, aml_int(pcihp_addr), 0x08));
629 field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
630 aml_append(field, aml_named_field("PCIU", 32));
631 aml_append(field, aml_named_field("PCID", 32));
632 aml_append(scope, field);
633
634 aml_append(scope,
635 aml_operation_region("SEJ", rs,
636 aml_int(pcihp_addr + ACPI_PCIHP_SEJ_BASE), 0x04));
637 field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
638 aml_append(field, aml_named_field("B0EJ", 32));
639 aml_append(scope, field);
640
641 aml_append(scope,
642 aml_operation_region("BNMR", rs,
643 aml_int(pcihp_addr + ACPI_PCIHP_BNMR_BASE), 0x08));
644 field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
645 aml_append(field, aml_named_field("BNUM", 32));
646 aml_append(field, aml_named_field("PIDX", 32));
647 aml_append(scope, field);
648
649 aml_append(scope, aml_mutex("BLCK", 0));
650
651 method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
652 aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
653 aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
654 aml_append(method,
655 aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
656 aml_append(method, aml_release(aml_name("BLCK")));
657 aml_append(method, aml_return(aml_int(0)));
658 aml_append(scope, method);
659
660 method = aml_method("AIDX", 2, AML_NOTSERIALIZED);
661 aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
662 aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
663 aml_append(method,
664 aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("PIDX")));
665 aml_append(method, aml_store(aml_name("PIDX"), aml_local(0)));
666 aml_append(method, aml_release(aml_name("BLCK")));
667 aml_append(method, aml_return(aml_local(0)));
668 aml_append(scope, method);
669
670 aml_append(scope, aml_pci_pdsm());
671
672 aml_append(table, scope);
673 }
674
675 /* Reserve PCIHP resources */
676 void build_append_pcihp_resources(Aml *scope /* \\_SB.PCI0 */,
677 uint64_t io_addr, uint64_t io_len)
678 {
679 Aml *dev, *crs;
680
681 dev = aml_device("PHPR");
682 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
683 aml_append(dev,
684 aml_name_decl("_UID", aml_string("PCI Hotplug resources")));
685 /* device present, functioning, decoding, not shown in UI */
686 aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
687 crs = aml_resource_template();
688 aml_append(crs, aml_io(AML_DECODE16, io_addr, io_addr, 1, io_len));
689 aml_append(dev, aml_name_decl("_CRS", crs));
690 aml_append(scope, dev);
691 }
692
693 bool build_append_notification_callback(Aml *parent_scope, const PCIBus *bus)
694 {
695 Aml *method;
696 PCIBus *sec;
697 QObject *bsel;
698 int nr_notifiers = 0;
699 GQueue *pcnt_bus_list = g_queue_new();
700
701 QLIST_FOREACH(sec, &bus->child, sibling) {
702 Aml *br_scope = aml_scope("S%.02X", sec->parent_dev->devfn);
703 if (pci_bus_is_root(sec)) {
704 continue;
705 }
706 nr_notifiers = nr_notifiers +
707 build_append_notification_callback(br_scope, sec);
708 /*
709 * add new child scope to parent
710 * and keep track of bus that have PCNT,
711 * bus list is used later to call children PCNTs from this level PCNT
712 */
713 if (nr_notifiers) {
714 g_queue_push_tail(pcnt_bus_list, sec);
715 aml_append(parent_scope, br_scope);
716 }
717 }
718
719 /*
720 * Append PCNT method to notify about events on local and child buses.
721 * ps: hostbridge might not have hotplug (bsel) enabled but might have
722 * child bridges that do have bsel.
723 */
724 method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
725
726 /* If bus supports hotplug select it and notify about local events */
727 bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
728 if (bsel) {
729 uint32_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
730
731 if (bsel_val != UINT32_MAX) {
732 aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
733 aml_append(method, aml_call2("DVNT", aml_name("PCIU"),
734 aml_int(1))); /* Device Check */
735 aml_append(method, aml_call2("DVNT", aml_name("PCID"),
736 aml_int(3))); /* Eject Request */
737 nr_notifiers++;
738 }
739 }
740
741 /* Notify about child bus events in any case */
742 while ((sec = g_queue_pop_head(pcnt_bus_list))) {
743 aml_append(method, aml_name("^S%.02X.PCNT", sec->parent_dev->devfn));
744 }
745
746 aml_append(parent_scope, method);
747 qobject_unref(bsel);
748 g_queue_free(pcnt_bus_list);
749 return !!nr_notifiers;
750 }
751
752 static Aml *aml_pci_device_dsm(void)
753 {
754 Aml *method;
755
756 method = aml_method("_DSM", 4, AML_SERIALIZED);
757 {
758 Aml *params = aml_local(0);
759 Aml *pkg = aml_package(2);
760 aml_append(pkg, aml_int(0));
761 aml_append(pkg, aml_int(0));
762 aml_append(method, aml_store(pkg, params));
763 aml_append(method,
764 aml_store(aml_name("BSEL"), aml_index(params, aml_int(0))));
765 aml_append(method,
766 aml_store(aml_name("ASUN"), aml_index(params, aml_int(1))));
767 aml_append(method,
768 aml_return(aml_call5("PDSM", aml_arg(0), aml_arg(1),
769 aml_arg(2), aml_arg(3), params))
770 );
771 }
772 return method;
773 }
774
775 static Aml *aml_pci_static_endpoint_dsm(PCIDevice *pdev)
776 {
777 Aml *method;
778
779 g_assert(pdev->acpi_index != 0);
780 method = aml_method("_DSM", 4, AML_SERIALIZED);
781 {
782 Aml *params = aml_local(0);
783 Aml *pkg = aml_package(1);
784 aml_append(pkg, aml_int(pdev->acpi_index));
785 aml_append(method, aml_store(pkg, params));
786 aml_append(method,
787 aml_return(aml_call5("EDSM", aml_arg(0), aml_arg(1),
788 aml_arg(2), aml_arg(3), params))
789 );
790 }
791 return method;
792 }
793
794 static void build_append_pcihp_notify_entry(Aml *method, int slot)
795 {
796 Aml *if_ctx;
797 int32_t devfn = PCI_DEVFN(slot, 0);
798
799 if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
800 aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
801 aml_append(method, if_ctx);
802 }
803
804 static bool is_devfn_ignored_generic(const int devfn, const PCIBus *bus)
805 {
806 const PCIDevice *pdev = bus->devices[devfn];
807
808 if (PCI_FUNC(devfn)) {
809 if (IS_PCI_BRIDGE(pdev)) {
810 /*
811 * Ignore only hotplugged PCI bridges on !0 functions, but
812 * allow describing cold plugged bridges on all functions
813 */
814 if (DEVICE(pdev)->hotplugged) {
815 return true;
816 }
817 }
818 }
819 return false;
820 }
821
822 static bool is_devfn_ignored_hotplug(const int devfn, const PCIBus *bus)
823 {
824 PCIDevice *pdev = bus->devices[devfn];
825 if (pdev) {
826 return is_devfn_ignored_generic(devfn, bus) ||
827 !DEVICE_GET_CLASS(pdev)->hotpluggable ||
828 /* Cold plugged bridges aren't themselves hot-pluggable */
829 (IS_PCI_BRIDGE(pdev) && !DEVICE(pdev)->hotplugged);
830 } else { /* non populated slots */
831 /*
832 * hotplug is supported only for non-multifunction device
833 * so generate device description only for function 0
834 */
835 if (PCI_FUNC(devfn) ||
836 (pci_bus_is_express(bus) && PCI_SLOT(devfn) > 0)) {
837 return true;
838 }
839 }
840 return false;
841 }
842
843 void build_append_pcihp_slots(Aml *parent_scope, PCIBus *bus)
844 {
845 int devfn;
846 Aml *dev, *notify_method = NULL, *method;
847 QObject *bsel = object_property_get_qobject(OBJECT(bus),
848 ACPI_PCIHP_PROP_BSEL, NULL);
849 uint32_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
850 qobject_unref(bsel);
851
852 aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
853 notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
854
855 for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
856 int slot = PCI_SLOT(devfn);
857 int adr = slot << 16 | PCI_FUNC(devfn);
858
859 if (is_devfn_ignored_hotplug(devfn, bus)) {
860 continue;
861 }
862
863 if (bus->devices[devfn]) {
864 dev = aml_scope("S%.02X", devfn);
865 } else {
866 dev = aml_device("S%.02X", devfn);
867 aml_append(dev, aml_name_decl("_ADR", aml_int(adr)));
868 }
869
870 /*
871 * Can't declare _SUN here for every device as it changes 'slot'
872 * enumeration order in linux kernel, so use another variable for it
873 */
874 aml_append(dev, aml_name_decl("ASUN", aml_int(slot)));
875 aml_append(dev, aml_pci_device_dsm());
876
877 aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
878 /* add _EJ0 to make slot hotpluggable */
879 method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
880 aml_append(method,
881 aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
882 );
883 aml_append(dev, method);
884
885 build_append_pcihp_notify_entry(notify_method, slot);
886
887 /* device descriptor has been composed, add it into parent context */
888 aml_append(parent_scope, dev);
889 }
890 aml_append(parent_scope, notify_method);
891 }
892
893 void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus)
894 {
895 int devfn;
896 Aml *dev;
897
898 for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
899 /* ACPI spec: 1.0b: Table 6-2 _ADR Object Bus Types, PCI type */
900 int adr = PCI_SLOT(devfn) << 16 | PCI_FUNC(devfn);
901 PCIDevice *pdev = bus->devices[devfn];
902
903 if (!pdev || is_devfn_ignored_generic(devfn, bus)) {
904 continue;
905 }
906
907 /* start to compose PCI device descriptor */
908 dev = aml_device("S%.02X", devfn);
909 aml_append(dev, aml_name_decl("_ADR", aml_int(adr)));
910
911 call_dev_aml_func(DEVICE(bus->devices[devfn]), dev);
912 /* add _DSM if device has acpi-index set */
913 if (pdev->acpi_index &&
914 !object_property_get_bool(OBJECT(pdev), "hotpluggable",
915 &error_abort)) {
916 aml_append(dev, aml_pci_static_endpoint_dsm(pdev));
917 }
918
919 /* device descriptor has been composed, add it into parent context */
920 aml_append(parent_scope, dev);
921 }
922 }
923
924 const VMStateDescription vmstate_acpi_pcihp_pci_status = {
925 .name = "acpi_pcihp_pci_status",
926 .version_id = 1,
927 .minimum_version_id = 1,
928 .fields = (const VMStateField[]) {
929 VMSTATE_UINT32(up, AcpiPciHpPciStatus),
930 VMSTATE_UINT32(down, AcpiPciHpPciStatus),
931 VMSTATE_END_OF_LIST()
932 }
933 };