xref: /openbmc/qemu/hw/acpi/pci-bridge.c (revision 0d70c5aa1bbfb0f5099d53d6e084337a8246cc0c)
1 /*
2  * QEMU ACPI PCI bridge
3  *
4  * Copyright (c) 2023 Red Hat, Inc.
5  *
6  * Author:
7  *   Igor Mammedov <imammedo@redhat.com>
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
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/acpi/pci.h"
17 #include "hw/pci/pci_bridge.h"
18 #include "hw/acpi/pcihp.h"
19 
20 void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope)
21 {
22     PCIBridge *br = PCI_BRIDGE(adev);
23 
24     if (!DEVICE(br)->hotplugged) {
25         PCIBus *sec_bus = pci_bridge_get_sec_bus(br);
26 
27         build_append_pci_bus_devices(scope, sec_bus);
28 
29         /*
30          * generate hotplug slots descriptors if
31          * bridge has ACPI PCI hotplug attached,
32          */
33         if (object_property_find(OBJECT(sec_bus), ACPI_PCIHP_PROP_BSEL)) {
34             build_append_pcihp_slots(scope, sec_bus);
35         }
36     }
37 }
38 
39 Aml *build_pci_bridge_edsm(void)
40 {
41     Aml *method, *ifctx;
42     Aml *zero = aml_int(0);
43     Aml *func = aml_arg(2);
44     Aml *ret = aml_local(0);
45     Aml *aidx = aml_local(1);
46     Aml *params = aml_arg(4);
47 
48     method = aml_method("EDSM", 5, AML_SERIALIZED);
49 
50     /* get supported functions */
51     ifctx = aml_if(aml_equal(func, zero));
52     {
53         /* 1: have supported functions */
54         /* 7: support for function 7 */
55         const uint8_t caps = 1 | BIT(7);
56         build_append_pci_dsm_func0_common(ifctx, ret);
57         aml_append(ifctx, aml_store(aml_int(caps), aml_index(ret, zero)));
58         aml_append(ifctx, aml_return(ret));
59     }
60     aml_append(method, ifctx);
61 
62     /* handle specific functions requests */
63     /*
64      * PCI Firmware Specification 3.1
65      * 4.6.7. _DSM for Naming a PCI or PCI Express Device Under
66      *        Operating Systems
67      */
68     ifctx = aml_if(aml_equal(func, aml_int(7)));
69     {
70        Aml *pkg = aml_package(2);
71        aml_append(pkg, zero);
72        /* optional, if not impl. should return null string */
73        aml_append(pkg, aml_string("%s", ""));
74        aml_append(ifctx, aml_store(pkg, ret));
75 
76        /*
77         * IASL is fine when initializing Package with computational data,
78         * however it makes guest unhappy /it fails to process such AML/.
79         * So use runtime assignment to set acpi-index after initializer
80         * to make OSPM happy.
81         */
82        aml_append(ifctx,
83            aml_store(aml_derefof(aml_index(params, aml_int(0))), aidx));
84        aml_append(ifctx, aml_store(aidx, aml_index(ret, zero)));
85        aml_append(ifctx, aml_return(ret));
86     }
87     aml_append(method, ifctx);
88 
89     return method;
90 }
91 
92