From nobody Thu Nov 6 14:34:07 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linux.intel.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1541383558511327.2252461072263; Sun, 4 Nov 2018 18:05:58 -0800 (PST) Received: from localhost ([::1]:32776 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gJUH6-0007B8-Su for importer@patchew.org; Sun, 04 Nov 2018 21:05:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47328) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gJTvJ-0000b2-AD for qemu-devel@nongnu.org; Sun, 04 Nov 2018 20:43:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gJTvD-0003PR-QC for qemu-devel@nongnu.org; Sun, 04 Nov 2018 20:43:22 -0500 Received: from mga05.intel.com ([192.55.52.43]:26671) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gJTv4-0003Ia-SG; Sun, 04 Nov 2018 20:43:11 -0500 Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Nov 2018 17:43:09 -0800 Received: from emurphy1-mobl1.ger.corp.intel.com (HELO localhost.localdomain) ([10.252.26.250]) by fmsmga005.fm.intel.com with ESMTP; 04 Nov 2018 17:43:04 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,466,1534834800"; d="scan'208";a="277074475" From: Samuel Ortiz To: qemu-devel@nongnu.org Date: Mon, 5 Nov 2018 02:40:40 +0100 Message-Id: <20181105014047.26447-18-sameo@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105014047.26447-1-sameo@linux.intel.com> References: <20181105014047.26447-1-sameo@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 192.55.52.43 Subject: [Qemu-devel] [PATCH v5 17/24] hw: acpi: Export the PCI hotplug API X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Stefano Stabellini , Eduardo Habkost , "Michael S. Tsirkin" , Jing Liu , Shannon Zhao , Igor Mammedov , qemu-arm@nongnu.org, Paolo Bonzini , Anthony Perard , xen-devel@lists.xenproject.org, Sebastien Boeuf , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" From: Sebastien Boeuf The ACPI hotplug support for PCI devices APIs are not x86 or even machine type specific. In order for future machine types to be able to re-use that code, we export it through the architecture agnostic hw/acpi folder. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Tested-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Sebastien Boeuf Signed-off-by: Jing Liu --- include/hw/acpi/aml-build.h | 3 + hw/acpi/aml-build.c | 194 ++++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 192 +---------------------------------- 3 files changed, 199 insertions(+), 190 deletions(-) diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 64ea371656..6b0a9735c5 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -418,6 +418,9 @@ Aml *build_osc_method(uint32_t value); void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info= ); Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi); Aml *build_prt(bool is_pci0_prt); +void build_acpi_pcihp(Aml *scope); +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, + bool pcihp_bridge_en); void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host); Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host); void crs_range_set_init(CrsRangeSet *range_set); diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 2c5446ab23..6112cc2149 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -34,6 +34,7 @@ #include "hw/acpi/tpm.h" #include "qom/qom-qobject.h" #include "qapi/qmp/qnum.h" +#include "hw/acpi/pcihp.h" =20 #define PCI_HOST_BRIDGE_CONFIG_ADDR 0xcf8 #define PCI_HOST_BRIDGE_IO_0_MIN_ADDR 0x0000 @@ -2305,6 +2306,199 @@ Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *= pci_host) return scope; } =20 +void build_acpi_pcihp(Aml *scope) +{ + Aml *field; + Aml *method; + + aml_append(scope, + aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08)= ); + field =3D aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZE= ROS); + aml_append(field, aml_named_field("PCIU", 32)); + aml_append(field, aml_named_field("PCID", 32)); + aml_append(scope, field); + + aml_append(scope, + aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04)); + field =3D aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZER= OS); + aml_append(field, aml_named_field("B0EJ", 32)); + aml_append(scope, field); + + aml_append(scope, + aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04)= ); + field =3D aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZE= ROS); + aml_append(field, aml_named_field("BNUM", 32)); + aml_append(scope, field); + + aml_append(scope, aml_mutex("BLCK", 0)); + + method =3D aml_method("PCEJ", 2, AML_NOTSERIALIZED); + aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF)); + aml_append(method, aml_store(aml_arg(0), aml_name("BNUM"))); + aml_append(method, + aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ"))= ); + aml_append(method, aml_release(aml_name("BLCK"))); + aml_append(method, aml_return(aml_int(0))); + aml_append(scope, method); +} + +static void build_append_pcihp_notify_entry(Aml *method, int slot) +{ + Aml *if_ctx; + int32_t devfn =3D PCI_DEVFN(slot, 0); + + if_ctx =3D aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL)); + aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1))); + aml_append(method, if_ctx); +} + +void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, + bool pcihp_bridge_en) +{ + Aml *dev, *notify_method =3D NULL, *method; + QObject *bsel; + PCIBus *sec; + int i; + + bsel =3D object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL= , NULL); + if (bsel) { + uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); + + aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val))); + notify_method =3D aml_method("DVNT", 2, AML_NOTSERIALIZED); + } + + for (i =3D 0; i < ARRAY_SIZE(bus->devices); i +=3D PCI_FUNC_MAX) { + DeviceClass *dc; + PCIDeviceClass *pc; + PCIDevice *pdev =3D bus->devices[i]; + int slot =3D PCI_SLOT(i); + bool hotplug_enabled_dev; + bool bridge_in_acpi; + + if (!pdev) { + if (bsel) { /* add hotplug slots for non present devices */ + dev =3D aml_device("S%.02X", PCI_DEVFN(slot, 0)); + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))= ); + method =3D aml_method("_EJ0", 1, AML_NOTSERIALIZED); + aml_append(method, + aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) + ); + aml_append(dev, method); + aml_append(parent_scope, dev); + + build_append_pcihp_notify_entry(notify_method, slot); + } + continue; + } + + pc =3D PCI_DEVICE_GET_CLASS(pdev); + dc =3D DEVICE_GET_CLASS(pdev); + + /* When hotplug for bridges is enabled, bridges are + * described in ACPI separately (see build_pci_bus_end). + * In this case they aren't themselves hot-pluggable. + * Hotplugged bridges *are* hot-pluggable. + */ + bridge_in_acpi =3D pc->is_bridge && pcihp_bridge_en && + !DEVICE(pdev)->hotplugged; + + hotplug_enabled_dev =3D bsel && dc->hotpluggable && !bridge_in_acp= i; + + if (pc->class_id =3D=3D PCI_CLASS_BRIDGE_ISA) { + continue; + } + + /* start to compose PCI slot descriptor */ + dev =3D aml_device("S%.02X", PCI_DEVFN(slot, 0)); + aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))); + + if (pc->class_id =3D=3D PCI_CLASS_DISPLAY_VGA) { + /* add VGA specific AML methods */ + int s3d; + + if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) { + s3d =3D 3; + } else { + s3d =3D 0; + } + + method =3D aml_method("_S1D", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(0))); + aml_append(dev, method); + + method =3D aml_method("_S2D", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(0))); + aml_append(dev, method); + + method =3D aml_method("_S3D", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(s3d))); + aml_append(dev, method); + } else if (hotplug_enabled_dev) { + /* add _SUN/_EJ0 to make slot hotpluggable */ + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + + method =3D aml_method("_EJ0", 1, AML_NOTSERIALIZED); + aml_append(method, + aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) + ); + aml_append(dev, method); + + if (bsel) { + build_append_pcihp_notify_entry(notify_method, slot); + } + } else if (bridge_in_acpi) { + /* + * device is coldplugged bridge, + * add child device descriptions into its scope + */ + PCIBus *sec_bus =3D pci_bridge_get_sec_bus(PCI_BRIDGE(pdev)); + + build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en); + } + /* slot descriptor has been composed, add it into parent context */ + aml_append(parent_scope, dev); + } + + if (bsel) { + aml_append(parent_scope, notify_method); + } + + /* Append PCNT method to notify about events on local and child buses. + * Add unconditionally for root since DSDT expects it. + */ + method =3D aml_method("PCNT", 0, AML_NOTSERIALIZED); + + /* If bus supports hotplug select it and notify about local events */ + if (bsel) { + uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); + + aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); + aml_append(method, + aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check= */) + ); + aml_append(method, + aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request= */) + ); + } + + /* Notify about child bus events in any case */ + if (pcihp_bridge_en) { + QLIST_FOREACH(sec, &bus->child, sibling) { + int32_t devfn =3D sec->parent_dev->devfn; + + if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) { + continue; + } + + aml_append(method, aml_name("^S%.02X.PCNT", devfn)); + } + } + aml_append(parent_scope, method); + qobject_unref(bsel); +} + void acpi_dsdt_add_pci_bus(Aml *dsdt, AcpiPciBus *pci_host) { Aml *dev, *pci_scope; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 673c5dfafc..bef5b23168 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -360,163 +360,6 @@ build_madt(GArray *table_data, BIOSLinker *linker, table_data->len - madt_start, 1, NULL, NULL); } =20 -static void build_append_pcihp_notify_entry(Aml *method, int slot) -{ - Aml *if_ctx; - int32_t devfn =3D PCI_DEVFN(slot, 0); - - if_ctx =3D aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL)); - aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1))); - aml_append(method, if_ctx); -} - -static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, - bool pcihp_bridge_en) -{ - Aml *dev, *notify_method =3D NULL, *method; - QObject *bsel; - PCIBus *sec; - int i; - - bsel =3D object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL= , NULL); - if (bsel) { - uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); - - aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val))); - notify_method =3D aml_method("DVNT", 2, AML_NOTSERIALIZED); - } - - for (i =3D 0; i < ARRAY_SIZE(bus->devices); i +=3D PCI_FUNC_MAX) { - DeviceClass *dc; - PCIDeviceClass *pc; - PCIDevice *pdev =3D bus->devices[i]; - int slot =3D PCI_SLOT(i); - bool hotplug_enabled_dev; - bool bridge_in_acpi; - - if (!pdev) { - if (bsel) { /* add hotplug slots for non present devices */ - dev =3D aml_device("S%.02X", PCI_DEVFN(slot, 0)); - aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); - aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))= ); - method =3D aml_method("_EJ0", 1, AML_NOTSERIALIZED); - aml_append(method, - aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) - ); - aml_append(dev, method); - aml_append(parent_scope, dev); - - build_append_pcihp_notify_entry(notify_method, slot); - } - continue; - } - - pc =3D PCI_DEVICE_GET_CLASS(pdev); - dc =3D DEVICE_GET_CLASS(pdev); - - /* When hotplug for bridges is enabled, bridges are - * described in ACPI separately (see build_pci_bus_end). - * In this case they aren't themselves hot-pluggable. - * Hotplugged bridges *are* hot-pluggable. - */ - bridge_in_acpi =3D pc->is_bridge && pcihp_bridge_en && - !DEVICE(pdev)->hotplugged; - - hotplug_enabled_dev =3D bsel && dc->hotpluggable && !bridge_in_acp= i; - - if (pc->class_id =3D=3D PCI_CLASS_BRIDGE_ISA) { - continue; - } - - /* start to compose PCI slot descriptor */ - dev =3D aml_device("S%.02X", PCI_DEVFN(slot, 0)); - aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))); - - if (pc->class_id =3D=3D PCI_CLASS_DISPLAY_VGA) { - /* add VGA specific AML methods */ - int s3d; - - if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) { - s3d =3D 3; - } else { - s3d =3D 0; - } - - method =3D aml_method("_S1D", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(0))); - aml_append(dev, method); - - method =3D aml_method("_S2D", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(0))); - aml_append(dev, method); - - method =3D aml_method("_S3D", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(s3d))); - aml_append(dev, method); - } else if (hotplug_enabled_dev) { - /* add _SUN/_EJ0 to make slot hotpluggable */ - aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); - - method =3D aml_method("_EJ0", 1, AML_NOTSERIALIZED); - aml_append(method, - aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) - ); - aml_append(dev, method); - - if (bsel) { - build_append_pcihp_notify_entry(notify_method, slot); - } - } else if (bridge_in_acpi) { - /* - * device is coldplugged bridge, - * add child device descriptions into its scope - */ - PCIBus *sec_bus =3D pci_bridge_get_sec_bus(PCI_BRIDGE(pdev)); - - build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en); - } - /* slot descriptor has been composed, add it into parent context */ - aml_append(parent_scope, dev); - } - - if (bsel) { - aml_append(parent_scope, notify_method); - } - - /* Append PCNT method to notify about events on local and child buses. - * Add unconditionally for root since DSDT expects it. - */ - method =3D aml_method("PCNT", 0, AML_NOTSERIALIZED); - - /* If bus supports hotplug select it and notify about local events */ - if (bsel) { - uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); - - aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); - aml_append(method, - aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check= */) - ); - aml_append(method, - aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request= */) - ); - } - - /* Notify about child bus events in any case */ - if (pcihp_bridge_en) { - QLIST_FOREACH(sec, &bus->child, sibling) { - int32_t devfn =3D sec->parent_dev->devfn; - - if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) { - continue; - } - - aml_append(method, aml_name("^S%.02X.PCNT", devfn)); - } - } - aml_append(parent_scope, method); - qobject_unref(bsel); -} - static void build_hpet_aml(Aml *table) { Aml *crs; @@ -1212,41 +1055,10 @@ static void build_piix4_isa_bridge(Aml *table) static void build_piix4_pci_hotplug(Aml *table) { Aml *scope; - Aml *field; - Aml *method; - - scope =3D aml_scope("_SB.PCI0"); - - aml_append(scope, - aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08)= ); - field =3D aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZE= ROS); - aml_append(field, aml_named_field("PCIU", 32)); - aml_append(field, aml_named_field("PCID", 32)); - aml_append(scope, field); =20 - aml_append(scope, - aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04)); - field =3D aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZER= OS); - aml_append(field, aml_named_field("B0EJ", 32)); - aml_append(scope, field); - - aml_append(scope, - aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04)= ); - field =3D aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZE= ROS); - aml_append(field, aml_named_field("BNUM", 32)); - aml_append(scope, field); - - aml_append(scope, aml_mutex("BLCK", 0)); - - method =3D aml_method("PCEJ", 2, AML_NOTSERIALIZED); - aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF)); - aml_append(method, aml_store(aml_arg(0), aml_name("BNUM"))); - aml_append(method, - aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ"))= ); - aml_append(method, aml_release(aml_name("BLCK"))); - aml_append(method, aml_return(aml_int(0))); - aml_append(scope, method); + scope =3D aml_scope("_SB.PCI0"); =20 + build_acpi_pcihp(scope); aml_append(table, scope); } =20 --=20 2.19.1