qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: Laurent Vivier <lvivier@redhat.com>, qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Jens Freimann <jfreimann@redhat.com>,
	Juan Quintela <quintela@redhat.com>
Subject: Re: [PATCH v6 1/6] qtest/libqos: add a function to initialize secondary PCI buses
Date: Tue, 7 Dec 2021 09:09:05 +0100	[thread overview]
Message-ID: <d754cc02-c4a7-17df-83c5-9120ba44a85d@redhat.com> (raw)
In-Reply-To: <20211206222040.3872253-2-lvivier@redhat.com>

On 06/12/2021 23.20, Laurent Vivier wrote:
> Scan the PCI devices to find bridge and set PCI_SECONDARY_BUS and
> PCI_SUBORDINATE_BUS (algorithm from seabios)
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
>   include/hw/pci/pci_bridge.h |   8 +++
>   tests/qtest/libqos/pci.c    | 118 ++++++++++++++++++++++++++++++++++++
>   tests/qtest/libqos/pci.h    |   1 +
>   3 files changed, 127 insertions(+)
> 
> diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
> index a94d350034bf..30691a6e5728 100644
> --- a/include/hw/pci/pci_bridge.h
> +++ b/include/hw/pci/pci_bridge.h
> @@ -138,6 +138,7 @@ typedef struct PCIBridgeQemuCap {
>       uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
>   } PCIBridgeQemuCap;
>   
> +#define REDHAT_PCI_CAP_TYPE_OFFSET      3
>   #define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
>   
>   /*
> @@ -152,6 +153,13 @@ typedef struct PCIResReserve {
>       uint64_t mem_pref_64;
>   } PCIResReserve;
>   
> +#define REDHAT_PCI_CAP_RES_RESERVE_BUS_RES     4
> +#define REDHAT_PCI_CAP_RES_RESERVE_IO          8
> +#define REDHAT_PCI_CAP_RES_RESERVE_MEM         16
> +#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_32 20
> +#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_64 24
> +#define REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE    32
> +
>   int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
>                                  PCIResReserve res_reserve, Error **errp);
>   
> diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
> index e1e96189c821..3f0b18f4750b 100644
> --- a/tests/qtest/libqos/pci.c
> +++ b/tests/qtest/libqos/pci.c
> @@ -13,6 +13,8 @@
>   #include "qemu/osdep.h"
>   #include "pci.h"
>   
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_bridge.h"
>   #include "hw/pci/pci_regs.h"
>   #include "qemu/host-utils.h"
>   #include "qgraph.h"
> @@ -99,6 +101,122 @@ void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr)
>       g_assert(!addr->device_id || device_id == addr->device_id);
>   }
>   
> +static uint8_t qpci_find_resource_reserve_capability(QPCIDevice *dev)
> +{
> +    uint16_t device_id;
> +    uint8_t cap = 0;
> +
> +    if (qpci_config_readw(dev, PCI_VENDOR_ID) != PCI_VENDOR_ID_REDHAT) {
> +        return 0;
> +    }
> +
> +    device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
> +
> +    if (device_id != PCI_DEVICE_ID_REDHAT_PCIE_RP &&
> +        device_id != PCI_DEVICE_ID_REDHAT_BRIDGE) {
> +        return 0;
> +    }
> +
> +    do {
> +        cap = qpci_find_capability(dev, PCI_CAP_ID_VNDR, cap);
> +    } while (cap &&
> +             qpci_config_readb(dev, cap + REDHAT_PCI_CAP_TYPE_OFFSET) !=
> +             REDHAT_PCI_CAP_RESOURCE_RESERVE);
> +    if (cap) {
> +        uint8_t cap_len = qpci_config_readb(dev, cap + PCI_CAP_FLAGS);
> +        if (cap_len < REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE) {
> +            return 0;
> +        }
> +    }
> +    return cap;
> +}
> +
> +static void qpci_secondary_buses_rec(QPCIBus *qbus, int bus, int *pci_bus)
> +{
> +    QPCIDevice *dev;
> +    uint16_t class;
> +    uint8_t pribus, secbus, subbus;
> +    int i;

<nit>I'd maybe use a better name instead of "i" here.</nit>

> +    for (i = 0; i < 32; i++) {
> +        dev = qpci_device_find(qbus, QPCI_DEVFN(bus + i, 0));
> +        if (dev == NULL) {
> +            continue;
> +        }
> +        class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
> +        if (class == PCI_CLASS_BRIDGE_PCI) {
> +            qpci_config_writeb(dev, PCI_SECONDARY_BUS, 255);
> +            qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 0);
> +        }
> +        g_free(dev);
> +    }
> +
> +    for (i = 0; i < 32; i++) {
> +        dev = qpci_device_find(qbus, QPCI_DEVFN(bus + i, 0));
> +        if (dev == NULL) {
> +            continue;
> +        }
> +        class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
> +        if (class != PCI_CLASS_BRIDGE_PCI) {
> +            continue;
> +        }
> +
> +        pribus = qpci_config_readb(dev, PCI_PRIMARY_BUS);
> +        if (pribus != bus) {
> +            qpci_config_writeb(dev, PCI_PRIMARY_BUS, bus);
> +        }
> +
> +        secbus = qpci_config_readb(dev, PCI_SECONDARY_BUS);
> +        (*pci_bus)++;
> +        if (*pci_bus != secbus) {
> +            secbus = *pci_bus;
> +            qpci_config_writeb(dev, PCI_SECONDARY_BUS, secbus);
> +        }
> +
> +        subbus = qpci_config_readb(dev, PCI_SUBORDINATE_BUS);
> +        qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 255);
> +
> +        qpci_secondary_buses_rec(qbus, secbus << 5, pci_bus);
> +
> +        if (subbus != *pci_bus) {
> +            uint8_t res_bus = *pci_bus;
> +            uint8_t cap = qpci_find_resource_reserve_capability(dev);
> +
> +            if (cap) {
> +                uint32_t tmp_res_bus;
> +
> +                tmp_res_bus = qpci_config_readl(dev, cap +
> +                                            REDHAT_PCI_CAP_RES_RESERVE_BUS_RES);
> +                if (tmp_res_bus != (uint32_t)-1) {
> +                    res_bus = tmp_res_bus & 0xFF;
> +                    if ((uint8_t)(res_bus + secbus) < secbus ||
> +                        (uint8_t)(res_bus + secbus) < res_bus) {
> +                        res_bus = 0;
> +                    }
> +                    if (secbus + res_bus > *pci_bus) {
> +                        res_bus = secbus + res_bus;
> +                    }
> +                }
> +            }
> +            subbus = res_bus;
> +            *pci_bus = res_bus;
> +        }
> +
> +        qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, subbus);
> +        g_free(dev);
> +    }
> +}
> +
> +int qpci_secondary_buses_init(QPCIBus *bus)
> +{
> +    int last_bus = 0;
> +
> +    qpci_secondary_buses_rec(bus, 0, &last_bus);
> +
> +    return last_bus;
> +}
> +
> +
>   void qpci_device_enable(QPCIDevice *dev)
>   {
>       uint16_t cmd;
> diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
> index ee64fdecbda8..becb800f9e6a 100644
> --- a/tests/qtest/libqos/pci.h
> +++ b/tests/qtest/libqos/pci.h
> @@ -81,6 +81,7 @@ void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
>                            void *data);
>   QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn);
>   void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr);
> +int qpci_secondary_buses_init(QPCIBus *bus);
>   
>   bool qpci_has_buggy_msi(QPCIDevice *dev);
>   bool qpci_check_buggy_msi(QPCIDevice *dev);
> 

Acked-by: Thomas Huth <thuth@redhat.com>



  reply	other threads:[~2021-12-07  8:10 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-06 22:20 [PATCH v6 0/6] tests/qtest: add some tests for virtio-net failover Laurent Vivier
2021-12-06 22:20 ` [PATCH v6 1/6] qtest/libqos: add a function to initialize secondary PCI buses Laurent Vivier
2021-12-07  8:09   ` Thomas Huth [this message]
2021-12-06 22:20 ` [PATCH v6 2/6] tests/qtest: add some tests for virtio-net failover Laurent Vivier
2021-12-07  8:29   ` Thomas Huth
2021-12-06 22:20 ` [PATCH v6 3/6] failover: fix unplug pending detection Laurent Vivier
2021-12-07  4:13   ` Ani Sinha
2021-12-07  7:31     ` Laurent Vivier
2021-12-06 22:20 ` [PATCH v6 4/6] tests/libqtest: update virtio-net failover test Laurent Vivier
2021-12-07  8:33   ` Thomas Huth
2021-12-06 22:20 ` [PATCH v6 5/6] test/libqtest: add some virtio-net failover migration cancelling tests Laurent Vivier
2021-12-07  8:35   ` Thomas Huth
2021-12-08  7:44   ` Michael S. Tsirkin
2021-12-08  7:48     ` Thomas Huth
2021-12-08  7:53       ` Thomas Huth
2021-12-06 22:20 ` [PATCH v6 6/6] tests/libqtest: add a migration test with two couples of failover devices Laurent Vivier
2021-12-07  8:39   ` Thomas Huth
2021-12-08  7:44 ` [PATCH v6 0/6] tests/qtest: add some tests for virtio-net failover Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d754cc02-c4a7-17df-83c5-9120ba44a85d@redhat.com \
    --to=thuth@redhat.com \
    --cc=jfreimann@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).