From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.8 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF785C04AB1 for ; Mon, 13 May 2019 06:21:48 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9961F20C01 for ; Mon, 13 May 2019 06:21:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.b="BRPC+jRn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9961F20C01 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([127.0.0.1]:51754 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hQ4LL-0004Dr-P5 for qemu-devel@archiver.kernel.org; Mon, 13 May 2019 02:21:47 -0400 Received: from eggs.gnu.org ([209.51.188.92]:35128) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hQ4JR-0002h8-Qi for qemu-devel@nongnu.org; Mon, 13 May 2019 02:19:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hQ4JQ-0004Li-7T for qemu-devel@nongnu.org; Mon, 13 May 2019 02:19:49 -0400 Received: from ozlabs.org ([203.11.71.1]:48883) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hQ4JP-0004KY-2I; Mon, 13 May 2019 02:19:48 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 452Vz26b8jz9sML; Mon, 13 May 2019 16:19:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1557728382; bh=2v7gcAXnr/JMTY471KXC7AVq3EN89FTOMlWJ929smXI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BRPC+jRngKY1seb7TUA0R9lQVUDARrXt8SIzwa1hHEbWNViv2XemGzgNswYbUApuY OvxyclK2wKPE17T6V33dyj3+untAZvk1HhModGQ51bG7jRTVn8UFDIMHu4+2/E7rJl BB3YSsHcodKPAN+ATjuhhU9HJFpPhEHUiN0oxbno= From: David Gibson To: mst@redhat.com, qemu-devel@nongnu.org Date: Mon, 13 May 2019 16:19:37 +1000 Message-Id: <20190513061939.3464-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190513061939.3464-1-david@gibson.dropbear.id.au> References: <20190513061939.3464-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 203.11.71.1 Subject: [Qemu-devel] [PATCH v4 3/5] pcie: Simplify pci_adjust_config_limit() 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: aik@ozlabs.ru, Mark Cave-Ayland , groug@kaod.org, qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Since c2077e2c "pci: Adjust PCI config limit based on bus topology", pci_adjust_config_limit() has been used in the config space read and writ= e paths to only permit access to extended config space on buses which permi= t it. Specifically it prevents access on devices below a vanilla-PCI bus v= ia some combination of bridges, even if both the host bridge and the device itself are PCI-E. It accomplishes this with a somewhat complex call up the chain of bridges to see if any of them prohibit extended config space access. This is overly complex, since we can always know if the bus will support such access at the point it is constructed. This patch simplifies the test by using a flag in the PCIBus instance indicating whether extended configuration space is accessible. It is false for vanilla PCI buses. For PCI-E buses, it is true for root buses and equal to the parent bus's's capability otherwise. For the special case of sPAPR's paravirtualized PCI root bus, which acts mostly like vanilla PCI, but does allow extended config space access, we override the default value of the flag from the host bridge code. This should cause no behavioural change. Signed-off-by: David Gibson Reviewed-by: Greg Kurz --- hw/pci/pci.c | 41 ++++++++++++++++++++++------------------ hw/pci/pci_host.c | 13 +++---------- hw/ppc/spapr_pci.c | 34 ++++++++++----------------------- include/hw/pci/pci.h | 1 - include/hw/pci/pci_bus.h | 8 +++++++- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b386777045..7e5f8d001b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **= errp) vmstate_register(NULL, -1, &vmstate_pcibus, bus); } =20 +static void pcie_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus =3D PCI_BUS(qbus); + + pci_bus_realize(qbus, errp); + + /* + * A PCI-E bus can support extended config space if it's the root + * bus, or if the bus/bridge above it does as well + */ + if (pci_bus_is_root(bus)) { + bus->flags |=3D PCI_BUS_EXTENDED_CONFIG_SPACE; + } else { + PCIBus *parent_bus =3D pci_get_bus(bus->parent_dev); + + if (pci_bus_allows_extended_config_space(parent_bus)) { + bus->flags |=3D PCI_BUS_EXTENDED_CONFIG_SPACE; + } + } +} + static void pci_bus_unrealize(BusState *qbus, Error **errp) { PCIBus *bus =3D PCI_BUS(qbus); @@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus) return NUMA_NODE_UNASSIGNED; } =20 -static bool pcibus_allows_extended_config_space(PCIBus *bus) -{ - return false; -} - static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k =3D BUS_CLASS(klass); @@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, vo= id *data) =20 pbc->bus_num =3D pcibus_num; pbc->numa_node =3D pcibus_numa_node; - pbc->allows_extended_config_space =3D pcibus_allows_extended_config_= space; } =20 static const TypeInfo pci_bus_info =3D { @@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_in= fo =3D { .parent =3D TYPE_INTERFACE, }; =20 -static bool pciebus_allows_extended_config_space(PCIBus *bus) -{ - return true; -} - static void pcie_bus_class_init(ObjectClass *klass, void *data) { - PCIBusClass *pbc =3D PCI_BUS_CLASS(klass); + BusClass *k =3D BUS_CLASS(klass); =20 - pbc->allows_extended_config_space =3D pciebus_allows_extended_config= _space; + k->realize =3D pcie_bus_realize; } =20 static const TypeInfo pcie_bus_info =3D { @@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus) return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); } =20 -bool pci_bus_allows_extended_config_space(PCIBus *bus) -{ - return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus); -} - void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState = *parent, const char *name, MemoryRegion *address_space_mem, diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 9d64b2e12f..5f3497256c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *= bus, uint32_t addr) =20 static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit) { - if (*limit > PCI_CONFIG_SPACE_SIZE) { - if (!pci_bus_allows_extended_config_space(bus)) { - *limit =3D PCI_CONFIG_SPACE_SIZE; - return; - } - - if (!pci_bus_is_root(bus)) { - PCIDevice *bridge =3D pci_bridge_get_device(bus); - pci_adjust_config_limit(pci_get_bus(bridge), limit); - } + if ((*limit > PCI_CONFIG_SPACE_SIZE) && + !pci_bus_allows_extended_config_space(bus)) { + *limit =3D PCI_CONFIG_SPACE_SIZE; } } =20 diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 97961b0128..9cf2c41b8c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, = Error **errp) memory_region_del_subregion(get_system_memory(), &sphb->mem32window)= ; } =20 -static bool spapr_phb_allows_extended_config_space(PCIBus *bus) -{ - SpaprPhbState *sphb =3D SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent); - - return sphb->pcie_ecs; -} - -static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data= ) -{ - PCIBusClass *pbc =3D PCI_BUS_CLASS(klass); - - pbc->allows_extended_config_space =3D spapr_phb_allows_extended_conf= ig_space; -} - -#define TYPE_SPAPR_PHB_ROOT_BUS "pci" - -static const TypeInfo spapr_phb_root_bus_info =3D { - .name =3D TYPE_SPAPR_PHB_ROOT_BUS, - .parent =3D TYPE_PCI_BUS, - .class_init =3D spapr_phb_root_bus_class_init, -}; - static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the u= ser @@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Er= ror **errp) pci_spapr_set_irq, pci_swizzle_map_irq_f= n, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, - TYPE_SPAPR_PHB_ROOT_BUS); + TYPE_PCI_BUS); + + /* + * Despite resembling a vanilla PCI bus in most ways, the PAPR + * para-virtualized PCI bus *does* permit PCI-E extended config + * space access + */ + if (sphb->pcie_ecs) { + bus->flags |=3D PCI_BUS_EXTENDED_CONFIG_SPACE; + } phb->bus =3D bus; qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); =20 @@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void) static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_phb_root_bus_info); } =20 type_init(spapr_pci_register_types) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index edf44de21d..da20c915ef 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque= , int pin); #define TYPE_PCIE_BUS "PCIE" =20 bool pci_bus_is_express(PCIBus *bus); -bool pci_bus_allows_extended_config_space(PCIBus *bus); =20 void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState = *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index aea98d5040..0714f578af 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -17,12 +17,13 @@ typedef struct PCIBusClass { =20 int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); - bool (*allows_extended_config_space)(PCIBus *bus); } PCIBusClass; =20 enum PCIBusFlags { /* This bus is the root of a PCI domain */ PCI_BUS_IS_ROOT =3D 0x0001, + /* PCIe extended configuration space is accessible on this bus */ + PCI_BUS_EXTENDED_CONFIG_SPACE =3D 0x0002, }; =20 struct PCIBus { @@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus) return !!(bus->flags & PCI_BUS_IS_ROOT); } =20 +static inline bool pci_bus_allows_extended_config_space(PCIBus *bus) +{ + return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE); +} + #endif /* QEMU_PCI_BUS_H */ --=20 2.21.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3427CC28CC0 for ; Wed, 29 May 2019 16:45:37 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AA6D123E2C for ; Wed, 29 May 2019 16:45:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AA6D123E2C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([127.0.0.1]:57971 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW1hn-0006W7-PG for qemu-devel@archiver.kernel.org; Wed, 29 May 2019 12:45:35 -0400 Received: from eggs.gnu.org ([209.51.188.92]:39605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hW1a0-0008VL-38 for qemu-devel@nongnu.org; Wed, 29 May 2019 12:37:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hW1Zy-0002ld-Ft for qemu-devel@nongnu.org; Wed, 29 May 2019 12:37:32 -0400 Received: from mail-qk1-f182.google.com ([209.85.222.182]:45710) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hW1Zy-0002lC-Bs for qemu-devel@nongnu.org; Wed, 29 May 2019 12:37:30 -0400 Received: by mail-qk1-f182.google.com with SMTP id j1so1851262qkk.12 for ; Wed, 29 May 2019 09:37:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=iR2D90tah69MokQaIVILyAA+SIy2IC9y7WqtDpQZwCc=; b=eyPI7EcX3MSQXGKJm8BhBTXYBkvTa//X62B7ch/tpb0z2Sjp1arHWWAl9BNESqwTFx 3E04eEGvxeVdwqxbFaMks5Q/9yne2/w/QObJNXCnCCRBJSVvtOdjNcCdK8SGvZLcYUPE 1PCAsAHPRiqOeFsT8VWx7Q6BOPBMRXTkCwc1VD+NeZiI6b+n4UQToRk8z0vCmdnuPc0O vbqVHIEruhFTzqiwy4ZpCgFW7pcqfjP9KZuo0y5NEf6at4eoEq+ae9VXpK7ScpM99kFO 17TMXgQX+3sbZyL+3zIDOTcrelhq/ImkBqVEWmt/c8VKy6X7QQirMRK+2U55e8tL1Dth gbEA== X-Gm-Message-State: APjAAAWfZ+rWtv+ZPK5h9CyUtZgoed19KT7gEzKEP5pYThZR7WGAj+3V zPo+k1Kcu/nVqgfuwjAP8RRYxrC5t7w= X-Google-Smtp-Source: APXvYqx/EPsnu5C2j4BasodRq4gh0oDHszKxCp5x3qcekSo+lKqUSP4rjMKOSYtndtOK1hW3EETpAw== X-Received: by 2002:ae9:d8c1:: with SMTP id u184mr457410qkf.352.1559147844604; Wed, 29 May 2019 09:37:24 -0700 (PDT) Received: from redhat.com (pool-100-0-197-103.bstnma.fios.verizon.net. [100.0.197.103]) by smtp.gmail.com with ESMTPSA id o71sm3728876qke.18.2019.05.29.09.37.22 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 29 May 2019 09:37:23 -0700 (PDT) Date: Wed, 29 May 2019 12:37:21 -0400 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <20190513061939.3464-4-david@gibson.dropbear.id.au> References: <20190529163604.18560-1-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline In-Reply-To: <20190529163604.18560-1-mst@redhat.com> X-Mailer: git-send-email 2.17.1.1206.gb667731e2e.dirty X-Mutt-Fcc: =sent X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.222.182 Subject: [Qemu-devel] [PULL 04/10] pcie: Simplify pci_adjust_config_limit() 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 , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Message-ID: <20190529163721.OaNX7-Jc-5Yw4DWcK5fWOZPBCGKhxVjYGFt448cZrfo@z> From: David Gibson Since c2077e2c "pci: Adjust PCI config limit based on bus topology", pci_adjust_config_limit() has been used in the config space read and write paths to only permit access to extended config space on buses which permit it. Specifically it prevents access on devices below a vanilla-PCI bus via some combination of bridges, even if both the host bridge and the device itself are PCI-E. It accomplishes this with a somewhat complex call up the chain of bridges to see if any of them prohibit extended config space access. This is overly complex, since we can always know if the bus will support such access at the point it is constructed. This patch simplifies the test by using a flag in the PCIBus instance indicating whether extended configuration space is accessible. It is false for vanilla PCI buses. For PCI-E buses, it is true for root buses and equal to the parent bus's's capability otherwise. For the special case of sPAPR's paravirtualized PCI root bus, which acts mostly like vanilla PCI, but does allow extended config space access, we override the default value of the flag from the host bridge code. This should cause no behavioural change. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Message-Id: <20190513061939.3464-4-david@gibson.dropbear.id.au> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 1 - include/hw/pci/pci_bus.h | 8 +++++++- hw/pci/pci.c | 41 ++++++++++++++++++++++------------------ hw/pci/pci_host.c | 13 +++---------- hw/ppc/spapr_pci.c | 34 ++++++++++----------------------- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index edf44de21d..da20c915ef 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); -bool pci_bus_allows_extended_config_space(PCIBus *bus); void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index aea98d5040..0714f578af 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -17,12 +17,13 @@ typedef struct PCIBusClass { int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); - bool (*allows_extended_config_space)(PCIBus *bus); } PCIBusClass; enum PCIBusFlags { /* This bus is the root of a PCI domain */ PCI_BUS_IS_ROOT = 0x0001, + /* PCIe extended configuration space is accessible on this bus */ + PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002, }; struct PCIBus { @@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus) return !!(bus->flags & PCI_BUS_IS_ROOT); } +static inline bool pci_bus_allows_extended_config_space(PCIBus *bus) +{ + return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE); +} + #endif /* QEMU_PCI_BUS_H */ diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b386777045..7e5f8d001b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **errp) vmstate_register(NULL, -1, &vmstate_pcibus, bus); } +static void pcie_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + pci_bus_realize(qbus, errp); + + /* + * A PCI-E bus can support extended config space if it's the root + * bus, or if the bus/bridge above it does as well + */ + if (pci_bus_is_root(bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } else { + PCIBus *parent_bus = pci_get_bus(bus->parent_dev); + + if (pci_bus_allows_extended_config_space(parent_bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } + } +} + static void pci_bus_unrealize(BusState *qbus, Error **errp) { PCIBus *bus = PCI_BUS(qbus); @@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus) return NUMA_NODE_UNASSIGNED; } -static bool pcibus_allows_extended_config_space(PCIBus *bus) -{ - return false; -} - static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) pbc->bus_num = pcibus_num; pbc->numa_node = pcibus_numa_node; - pbc->allows_extended_config_space = pcibus_allows_extended_config_space; } static const TypeInfo pci_bus_info = { @@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_info = { .parent = TYPE_INTERFACE, }; -static bool pciebus_allows_extended_config_space(PCIBus *bus) -{ - return true; -} - static void pcie_bus_class_init(ObjectClass *klass, void *data) { - PCIBusClass *pbc = PCI_BUS_CLASS(klass); + BusClass *k = BUS_CLASS(klass); - pbc->allows_extended_config_space = pciebus_allows_extended_config_space; + k->realize = pcie_bus_realize; } static const TypeInfo pcie_bus_info = { @@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus) return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); } -bool pci_bus_allows_extended_config_space(PCIBus *bus) -{ - return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus); -} - void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 9d64b2e12f..5f3497256c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit) { - if (*limit > PCI_CONFIG_SPACE_SIZE) { - if (!pci_bus_allows_extended_config_space(bus)) { - *limit = PCI_CONFIG_SPACE_SIZE; - return; - } - - if (!pci_bus_is_root(bus)) { - PCIDevice *bridge = pci_bridge_get_device(bus); - pci_adjust_config_limit(pci_get_bus(bridge), limit); - } + if ((*limit > PCI_CONFIG_SPACE_SIZE) && + !pci_bus_allows_extended_config_space(bus)) { + *limit = PCI_CONFIG_SPACE_SIZE; } } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 97961b0128..9cf2c41b8c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) memory_region_del_subregion(get_system_memory(), &sphb->mem32window); } -static bool spapr_phb_allows_extended_config_space(PCIBus *bus) -{ - SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent); - - return sphb->pcie_ecs; -} - -static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data) -{ - PCIBusClass *pbc = PCI_BUS_CLASS(klass); - - pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space; -} - -#define TYPE_SPAPR_PHB_ROOT_BUS "pci" - -static const TypeInfo spapr_phb_root_bus_info = { - .name = TYPE_SPAPR_PHB_ROOT_BUS, - .parent = TYPE_PCI_BUS, - .class_init = spapr_phb_root_bus_class_init, -}; - static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, - TYPE_SPAPR_PHB_ROOT_BUS); + TYPE_PCI_BUS); + + /* + * Despite resembling a vanilla PCI bus in most ways, the PAPR + * para-virtualized PCI bus *does* permit PCI-E extended config + * space access + */ + if (sphb->pcie_ecs) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } phb->bus = bus; qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); @@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void) static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_phb_root_bus_info); } type_init(spapr_pci_register_types) -- MST From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A465DC04AB5 for ; Mon, 3 Jun 2019 18:14:07 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7390625031 for ; Mon, 3 Jun 2019 18:14:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7390625031 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([127.0.0.1]:39011 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hXrTC-0005qJ-F7 for qemu-devel@archiver.kernel.org; Mon, 03 Jun 2019 14:14:06 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56316) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hXrNs-0001mK-ST for qemu-devel@nongnu.org; Mon, 03 Jun 2019 14:08:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hXrNr-0007ya-9c for qemu-devel@nongnu.org; Mon, 03 Jun 2019 14:08:36 -0400 Received: from mail-qt1-f175.google.com ([209.85.160.175]:33349) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hXrNr-0007x5-3c for qemu-devel@nongnu.org; Mon, 03 Jun 2019 14:08:35 -0400 Received: by mail-qt1-f175.google.com with SMTP id 14so10574148qtf.0 for ; Mon, 03 Jun 2019 11:08:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=iR2D90tah69MokQaIVILyAA+SIy2IC9y7WqtDpQZwCc=; b=s63ciVlzKOzJp8d+cvxnKFR58UxzWJinT0nxevBOsBpPOXuk84ROMdL74RcK2ywbA4 7zaGF4hsZnIO6QGdi75G6Bf78H22dk6QLvEFkRLUaQYbPThrYChK2NsbGz/4PhWokgfb szVoyNhNEnfip4YuVxED/dexxTt/O7TmVpwESTeG1Z5WU8l2b3IX6pSLfQPYuo/tx5VA xNnMtpgOl+JYUPBY8pcBMdxmPqtNXWx24rnmtZ1/f9wNxhmyyH9ovRomlfoCNHhaH43f thOOUI/SZRj0s5QSYGmQXgvm1oqpNSYF8xns+saMFlwqjIturdwVtyidWcFPTahxDIgy J/+g== X-Gm-Message-State: APjAAAXOGNW778oJpKc8C4RK+7glzzpOmmuaIJqfZKf7NkPV/fzvHezX mmrqI9QwdWoq53qrggkRra7YO9aOkDI= X-Google-Smtp-Source: APXvYqwBDYGwpLqGCxIYe1aWRbRQIx/89iYg4/gFXExRMA9NRz+hlbegwrUilEhokQT+4EvruOUn3A== X-Received: by 2002:a0c:8b54:: with SMTP id d20mr23173621qvc.1.1559585313971; Mon, 03 Jun 2019 11:08:33 -0700 (PDT) Received: from redhat.com (pool-100-0-197-103.bstnma.fios.verizon.net. [100.0.197.103]) by smtp.gmail.com with ESMTPSA id n7sm9063928qkd.53.2019.06.03.11.08.32 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Mon, 03 Jun 2019 11:08:33 -0700 (PDT) Date: Mon, 3 Jun 2019 14:08:31 -0400 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <20190513061939.3464-4-david@gibson.dropbear.id.au> References: <20190603180807.16140-1-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline In-Reply-To: <20190603180807.16140-1-mst@redhat.com> X-Mailer: git-send-email 2.17.1.1206.gb667731e2e.dirty X-Mutt-Fcc: =sent X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.160.175 Subject: [Qemu-devel] [PULL v2 03/14] pcie: Simplify pci_adjust_config_limit() 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 , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Message-ID: <20190603180831.yDeOhKczxo-ThCbno_7lRRW7DjIsiisH1ehk1KJRJ6Q@z> From: David Gibson Since c2077e2c "pci: Adjust PCI config limit based on bus topology", pci_adjust_config_limit() has been used in the config space read and write paths to only permit access to extended config space on buses which permit it. Specifically it prevents access on devices below a vanilla-PCI bus via some combination of bridges, even if both the host bridge and the device itself are PCI-E. It accomplishes this with a somewhat complex call up the chain of bridges to see if any of them prohibit extended config space access. This is overly complex, since we can always know if the bus will support such access at the point it is constructed. This patch simplifies the test by using a flag in the PCIBus instance indicating whether extended configuration space is accessible. It is false for vanilla PCI buses. For PCI-E buses, it is true for root buses and equal to the parent bus's's capability otherwise. For the special case of sPAPR's paravirtualized PCI root bus, which acts mostly like vanilla PCI, but does allow extended config space access, we override the default value of the flag from the host bridge code. This should cause no behavioural change. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Message-Id: <20190513061939.3464-4-david@gibson.dropbear.id.au> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 1 - include/hw/pci/pci_bus.h | 8 +++++++- hw/pci/pci.c | 41 ++++++++++++++++++++++------------------ hw/pci/pci_host.c | 13 +++---------- hw/ppc/spapr_pci.c | 34 ++++++++++----------------------- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index edf44de21d..da20c915ef 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); -bool pci_bus_allows_extended_config_space(PCIBus *bus); void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index aea98d5040..0714f578af 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -17,12 +17,13 @@ typedef struct PCIBusClass { int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); - bool (*allows_extended_config_space)(PCIBus *bus); } PCIBusClass; enum PCIBusFlags { /* This bus is the root of a PCI domain */ PCI_BUS_IS_ROOT = 0x0001, + /* PCIe extended configuration space is accessible on this bus */ + PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002, }; struct PCIBus { @@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus) return !!(bus->flags & PCI_BUS_IS_ROOT); } +static inline bool pci_bus_allows_extended_config_space(PCIBus *bus) +{ + return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE); +} + #endif /* QEMU_PCI_BUS_H */ diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b386777045..7e5f8d001b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **errp) vmstate_register(NULL, -1, &vmstate_pcibus, bus); } +static void pcie_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + pci_bus_realize(qbus, errp); + + /* + * A PCI-E bus can support extended config space if it's the root + * bus, or if the bus/bridge above it does as well + */ + if (pci_bus_is_root(bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } else { + PCIBus *parent_bus = pci_get_bus(bus->parent_dev); + + if (pci_bus_allows_extended_config_space(parent_bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } + } +} + static void pci_bus_unrealize(BusState *qbus, Error **errp) { PCIBus *bus = PCI_BUS(qbus); @@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus) return NUMA_NODE_UNASSIGNED; } -static bool pcibus_allows_extended_config_space(PCIBus *bus) -{ - return false; -} - static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) pbc->bus_num = pcibus_num; pbc->numa_node = pcibus_numa_node; - pbc->allows_extended_config_space = pcibus_allows_extended_config_space; } static const TypeInfo pci_bus_info = { @@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_info = { .parent = TYPE_INTERFACE, }; -static bool pciebus_allows_extended_config_space(PCIBus *bus) -{ - return true; -} - static void pcie_bus_class_init(ObjectClass *klass, void *data) { - PCIBusClass *pbc = PCI_BUS_CLASS(klass); + BusClass *k = BUS_CLASS(klass); - pbc->allows_extended_config_space = pciebus_allows_extended_config_space; + k->realize = pcie_bus_realize; } static const TypeInfo pcie_bus_info = { @@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus) return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); } -bool pci_bus_allows_extended_config_space(PCIBus *bus) -{ - return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus); -} - void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 9d64b2e12f..5f3497256c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit) { - if (*limit > PCI_CONFIG_SPACE_SIZE) { - if (!pci_bus_allows_extended_config_space(bus)) { - *limit = PCI_CONFIG_SPACE_SIZE; - return; - } - - if (!pci_bus_is_root(bus)) { - PCIDevice *bridge = pci_bridge_get_device(bus); - pci_adjust_config_limit(pci_get_bus(bridge), limit); - } + if ((*limit > PCI_CONFIG_SPACE_SIZE) && + !pci_bus_allows_extended_config_space(bus)) { + *limit = PCI_CONFIG_SPACE_SIZE; } } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 97961b0128..9cf2c41b8c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) memory_region_del_subregion(get_system_memory(), &sphb->mem32window); } -static bool spapr_phb_allows_extended_config_space(PCIBus *bus) -{ - SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent); - - return sphb->pcie_ecs; -} - -static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data) -{ - PCIBusClass *pbc = PCI_BUS_CLASS(klass); - - pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space; -} - -#define TYPE_SPAPR_PHB_ROOT_BUS "pci" - -static const TypeInfo spapr_phb_root_bus_info = { - .name = TYPE_SPAPR_PHB_ROOT_BUS, - .parent = TYPE_PCI_BUS, - .class_init = spapr_phb_root_bus_class_init, -}; - static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, - TYPE_SPAPR_PHB_ROOT_BUS); + TYPE_PCI_BUS); + + /* + * Despite resembling a vanilla PCI bus in most ways, the PAPR + * para-virtualized PCI bus *does* permit PCI-E extended config + * space access + */ + if (sphb->pcie_ecs) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } phb->bus = bus; qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); @@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void) static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_phb_root_bus_info); } type_init(spapr_pci_register_types) -- MST From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1AD0C28CC5 for ; Wed, 5 Jun 2019 20:07:21 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 332C3206BB for ; Wed, 5 Jun 2019 20:07:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 332C3206BB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([127.0.0.1]:49151 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hYcBs-000829-6O for qemu-devel@archiver.kernel.org; Wed, 05 Jun 2019 16:07:20 -0400 Received: from eggs.gnu.org ([209.51.188.92]:33985) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hYc5K-00031d-AO for qemu-devel@nongnu.org; Wed, 05 Jun 2019 16:00:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hYc5I-0005Tl-AS for qemu-devel@nongnu.org; Wed, 05 Jun 2019 16:00:34 -0400 Received: from mail-qt1-f180.google.com ([209.85.160.180]:39745) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hYc5H-0004wo-9n for qemu-devel@nongnu.org; Wed, 05 Jun 2019 16:00:32 -0400 Received: by mail-qt1-f180.google.com with SMTP id i34so6103790qta.6 for ; Wed, 05 Jun 2019 13:00:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=iR2D90tah69MokQaIVILyAA+SIy2IC9y7WqtDpQZwCc=; b=bsloq+2DPK4mJooqIevtfZ5vrnZ5rxUf/rHHgio20jqPYRWwt42wAgp0qqSb07kCLA jwDvFEOw4zxQT7F3hYgicRMhcEH85whb0RVtTl/d17vstp+G3nqA7cZMCSjKu7ggymVV 1fyVZzMlX4zJ/UJgncRhKwdIyuGbxp94PcdU7MUOhPSLp4cStODvJcnhmcVWyNfjiQvC Ui0vhIS03ns4NjV+rhqJ+nlX1Is9JXlOhVR4XnffaWEVF4e1uC0dfz23aMzC7TzQDY7K PB13VuoRw4YXwBgzc/TCyvH4Uh7krc5y1BxI02hljTKer9DqnQWwGBTgqzkhTvnXxWDd /L1A== X-Gm-Message-State: APjAAAWmckYDq5MXPWHo1CkURA7HIRkaTijJKHzuFIv2ohGA5UVXwPfk 8W/ZzdM3bJXchJa0q3Sj1gDejFQKcnY= X-Google-Smtp-Source: APXvYqwlD2YEC1fGT7ytr+H5IVmfS38gJYQGJrjUsShmeJ706z8LxFD98qoTXABsiZkOddkO1t6x3w== X-Received: by 2002:aed:22a9:: with SMTP id p38mr13404584qtc.188.1559764813357; Wed, 05 Jun 2019 13:00:13 -0700 (PDT) Received: from redhat.com (pool-100-0-197-103.bstnma.fios.verizon.net. [100.0.197.103]) by smtp.gmail.com with ESMTPSA id f6sm7174977qkk.79.2019.06.05.13.00.12 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 05 Jun 2019 13:00:12 -0700 (PDT) Date: Wed, 5 Jun 2019 16:00:11 -0400 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <20190513061939.3464-4-david@gibson.dropbear.id.au> References: <20190605195913.12243-1-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline In-Reply-To: <20190605195913.12243-1-mst@redhat.com> X-Mailer: git-send-email 2.17.1.1206.gb667731e2e.dirty X-Mutt-Fcc: =sent X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.160.180 Subject: [Qemu-devel] [PULL v3 03/17] pcie: Simplify pci_adjust_config_limit() 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 , qemu-ppc@nongnu.org, Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Message-ID: <20190605200011.P48ZVYhfuA6wGzOAwTykngso24_0ed6cV-JNu_9azTA@z> From: David Gibson Since c2077e2c "pci: Adjust PCI config limit based on bus topology", pci_adjust_config_limit() has been used in the config space read and write paths to only permit access to extended config space on buses which permit it. Specifically it prevents access on devices below a vanilla-PCI bus via some combination of bridges, even if both the host bridge and the device itself are PCI-E. It accomplishes this with a somewhat complex call up the chain of bridges to see if any of them prohibit extended config space access. This is overly complex, since we can always know if the bus will support such access at the point it is constructed. This patch simplifies the test by using a flag in the PCIBus instance indicating whether extended configuration space is accessible. It is false for vanilla PCI buses. For PCI-E buses, it is true for root buses and equal to the parent bus's's capability otherwise. For the special case of sPAPR's paravirtualized PCI root bus, which acts mostly like vanilla PCI, but does allow extended config space access, we override the default value of the flag from the host bridge code. This should cause no behavioural change. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Message-Id: <20190513061939.3464-4-david@gibson.dropbear.id.au> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 1 - include/hw/pci/pci_bus.h | 8 +++++++- hw/pci/pci.c | 41 ++++++++++++++++++++++------------------ hw/pci/pci_host.c | 13 +++---------- hw/ppc/spapr_pci.c | 34 ++++++++++----------------------- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index edf44de21d..da20c915ef 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); -bool pci_bus_allows_extended_config_space(PCIBus *bus); void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index aea98d5040..0714f578af 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -17,12 +17,13 @@ typedef struct PCIBusClass { int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); - bool (*allows_extended_config_space)(PCIBus *bus); } PCIBusClass; enum PCIBusFlags { /* This bus is the root of a PCI domain */ PCI_BUS_IS_ROOT = 0x0001, + /* PCIe extended configuration space is accessible on this bus */ + PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002, }; struct PCIBus { @@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus) return !!(bus->flags & PCI_BUS_IS_ROOT); } +static inline bool pci_bus_allows_extended_config_space(PCIBus *bus) +{ + return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE); +} + #endif /* QEMU_PCI_BUS_H */ diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b386777045..7e5f8d001b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **errp) vmstate_register(NULL, -1, &vmstate_pcibus, bus); } +static void pcie_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + pci_bus_realize(qbus, errp); + + /* + * A PCI-E bus can support extended config space if it's the root + * bus, or if the bus/bridge above it does as well + */ + if (pci_bus_is_root(bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } else { + PCIBus *parent_bus = pci_get_bus(bus->parent_dev); + + if (pci_bus_allows_extended_config_space(parent_bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } + } +} + static void pci_bus_unrealize(BusState *qbus, Error **errp) { PCIBus *bus = PCI_BUS(qbus); @@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus) return NUMA_NODE_UNASSIGNED; } -static bool pcibus_allows_extended_config_space(PCIBus *bus) -{ - return false; -} - static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) pbc->bus_num = pcibus_num; pbc->numa_node = pcibus_numa_node; - pbc->allows_extended_config_space = pcibus_allows_extended_config_space; } static const TypeInfo pci_bus_info = { @@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_info = { .parent = TYPE_INTERFACE, }; -static bool pciebus_allows_extended_config_space(PCIBus *bus) -{ - return true; -} - static void pcie_bus_class_init(ObjectClass *klass, void *data) { - PCIBusClass *pbc = PCI_BUS_CLASS(klass); + BusClass *k = BUS_CLASS(klass); - pbc->allows_extended_config_space = pciebus_allows_extended_config_space; + k->realize = pcie_bus_realize; } static const TypeInfo pcie_bus_info = { @@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus) return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); } -bool pci_bus_allows_extended_config_space(PCIBus *bus) -{ - return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus); -} - void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 9d64b2e12f..5f3497256c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit) { - if (*limit > PCI_CONFIG_SPACE_SIZE) { - if (!pci_bus_allows_extended_config_space(bus)) { - *limit = PCI_CONFIG_SPACE_SIZE; - return; - } - - if (!pci_bus_is_root(bus)) { - PCIDevice *bridge = pci_bridge_get_device(bus); - pci_adjust_config_limit(pci_get_bus(bridge), limit); - } + if ((*limit > PCI_CONFIG_SPACE_SIZE) && + !pci_bus_allows_extended_config_space(bus)) { + *limit = PCI_CONFIG_SPACE_SIZE; } } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 97961b0128..9cf2c41b8c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) memory_region_del_subregion(get_system_memory(), &sphb->mem32window); } -static bool spapr_phb_allows_extended_config_space(PCIBus *bus) -{ - SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent); - - return sphb->pcie_ecs; -} - -static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data) -{ - PCIBusClass *pbc = PCI_BUS_CLASS(klass); - - pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space; -} - -#define TYPE_SPAPR_PHB_ROOT_BUS "pci" - -static const TypeInfo spapr_phb_root_bus_info = { - .name = TYPE_SPAPR_PHB_ROOT_BUS, - .parent = TYPE_PCI_BUS, - .class_init = spapr_phb_root_bus_class_init, -}; - static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, - TYPE_SPAPR_PHB_ROOT_BUS); + TYPE_PCI_BUS); + + /* + * Despite resembling a vanilla PCI bus in most ways, the PAPR + * para-virtualized PCI bus *does* permit PCI-E extended config + * space access + */ + if (sphb->pcie_ecs) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } phb->bus = bus; qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); @@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void) static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_phb_root_bus_info); } type_init(spapr_pci_register_types) -- MST