From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alexey Korolev <alexey.korolev@endace.com>
Cc: sfd@endace.com, yamahata@valinux.co.jp, seabios@seabios.org,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 3/3] Changes related to secondary buses and 64bit regions
Date: Wed, 28 Dec 2011 13:43:02 +0200 [thread overview]
Message-ID: <20111228114302.GB26310@redhat.com> (raw)
In-Reply-To: <4EFAAABB.3020804@endace.com>
On Wed, Dec 28, 2011 at 06:35:55PM +1300, Alexey Korolev wrote:
> All devices behind a bridge need to have all their regions consecutive and
> not overlapping with all the normal memory ranges.
> Since prefetchable memory is described by one record, we must avoid the situations
> when 32bit and 64bit prefetchable regions are present within one secondary bus.
How do we avoid this? Assume we have two devices:
a 32 bit and a 64 bit one, behind a bridge.
There are two main things we can do:
1. Make the 64 bit device only use the low 32 bit
2. Put the 32 bit one in the non-prefetcheable range
1 probably makes more sense for small BARs
2 probably makes more sense for large ones
Try also looking at e.g. linux bus scanning code for more ideas.
Another thing I don't see addressed here is that support for 64 bit
ranges is I think optional in the bridge.
>
> Signed-off-by: Alexey Korolev<alexey.korolev@endace.com>
Whitespace is corrupted: checkyour mail setup?
There should be spaces around operators:
a < b, I see a< b. Sometimes a< b (two spaces after).
> ---
> src/pciinit.c | 69 +++++++++++++++++++++++++++++++++++++++-----------------
> 1 files changed, 48 insertions(+), 21 deletions(-)
>
> diff --git a/src/pciinit.c b/src/pciinit.c
> index a574e38..92942d5 100644
> --- a/src/pciinit.c
> +++ b/src/pciinit.c
> @@ -17,6 +17,7 @@
>
> #define PCI_BRIDGE_IO_MIN 0x1000
> #define PCI_BRIDGE_MEM_MIN 0x100000
> +#define PCI_BRIDGE_MEM_MAX 0x80000000
>
> enum pci_region_type {
> PCI_REGION_TYPE_IO,
> @@ -45,6 +46,7 @@ struct pci_bus {
> s64 base;
> s64 bases[32 - PCI_MEM_INDEX_SHIFT];
> } r[PCI_REGION_TYPE_COUNT];
> + int is64;
> struct pci_device *bus_dev;
> };
>
> @@ -369,6 +371,26 @@ static void pci_bios_bus_reserve(struct pci_bus *bus, int type, u32 size)
> bus->r[type].max = size;
> }
>
> +static void pci_bios_secondary_bus_reserve(struct pci_bus *parent,
> + struct pci_bus *s, int type)
> +{
> + u32 limit = (type == PCI_REGION_TYPE_IO) ?
> + PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
> +
> + if (s->r[type].sum> PCI_BRIDGE_MEM_MAX) {
> + panic("Size: %08x%08x is too big\n",
> + (u32)s->r[type].sum, (u32)(s->r[type].sum>>32));
> + }
> + s->r[type].size = (u32)s->r[type].sum;
> + if (s->r[type].size< limit)
> + s->r[type].size = limit;
> + s->r[type].size = pci_size_roundup(s->r[type].size);
> +
> + pci_bios_bus_reserve(parent, type, s->r[type].size);
> + dprintf(1, " size: %x, type %s\n",
> + s->r[type].size, region_type_name[type]);
> +}
> +
> static void pci_bios_check_devices(struct pci_bus *busses)
> {
> dprintf(1, "PCI: check devices\n");
> @@ -392,8 +414,10 @@ static void pci_bios_check_devices(struct pci_bus *busses)
> pci_bios_bus_reserve(bus, type, size);
> pci->bars[i].addr = val;
> pci->bars[i].size = size;
> - if (type == PCI_REGION_TYPE_PREFMEM_64)
> + if (type == PCI_REGION_TYPE_PREFMEM_64) {
> + bus->is64 = 1;
> i++;
> + }
> }
> }
>
> @@ -404,22 +428,21 @@ static void pci_bios_check_devices(struct pci_bus *busses)
> if (!s->bus_dev)
> continue;
> struct pci_bus *parent =&busses[pci_bdf_to_bus(s->bus_dev->bdf)];
> +
> + if (s->r[PCI_REGION_TYPE_PREFMEM_64].sum&&
Space before && here and elsewhere.
> + s->r[PCI_REGION_TYPE_PREFMEM].sum) {
> + panic("Sparse PCI prefmem regions on the bus %d\n", secondary_bus);
> + }
> +
> + dprintf(1, "PCI: secondary bus %d\n", secondary_bus);
> int type;
> for (type = 0; type< PCI_REGION_TYPE_COUNT; type++) {
> - u32 limit = (type == PCI_REGION_TYPE_IO) ?
> - PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
> - s->r[type].size = s->r[type].sum;
> - if (s->r[type].size< limit)
> - s->r[type].size = limit;
> - s->r[type].size = pci_size_roundup(s->r[type].size);
> - pci_bios_bus_reserve(parent, type, s->r[type].size);
> - }
> - dprintf(1, "PCI: secondary bus %d sizes: io %x, mem %x, prefmem %x\n",
> - secondary_bus,
> - s->r[PCI_REGION_TYPE_IO].size,
> - s->r[PCI_REGION_TYPE_MEM].size,
> - s->r[PCI_REGION_TYPE_PREFMEM].size);
> - }
> + if ((type == PCI_REGION_TYPE_PREFMEM_64&& !s->is64) ||
> + (type == PCI_REGION_TYPE_PREFMEM&& s->is64))
> + continue;
Can't figure this out. What does this do?
> + pci_bios_secondary_bus_reserve(parent, s, type);
> + }
> + }
> }
>
> #define ROOT_BASE(top, sum, max) ALIGN_DOWN((top)-(sum),(max) ?: 1)
> @@ -507,14 +530,17 @@ static void pci_bios_map_devices(struct pci_bus *busses)
> struct pci_bus *parent =&busses[pci_bdf_to_bus(bdf)];
> int type;
> for (type = 0; type< PCI_REGION_TYPE_COUNT; type++) {
> + if ((type == PCI_REGION_TYPE_PREFMEM_64&& !s->is64) ||
> + (type == PCI_REGION_TYPE_PREFMEM&& s->is64))
> + continue;
> s->r[type].base = pci_bios_bus_get_addr(
> parent, type, s->r[type].size);
> }
> dprintf(1, "PCI: init bases bus %d (secondary)\n", secondary_bus);
> pci_bios_init_bus_bases(s);
>
> - u32 base = s->r[PCI_REGION_TYPE_IO].base;
> - u32 limit = base + s->r[PCI_REGION_TYPE_IO].size - 1;
> + s64 base = s->r[PCI_REGION_TYPE_IO].base;
> + s64 limit = base + s->r[PCI_REGION_TYPE_IO].size - 1;
> pci_config_writeb(bdf, PCI_IO_BASE, base>> PCI_IO_SHIFT);
> pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
> pci_config_writeb(bdf, PCI_IO_LIMIT, limit>> PCI_IO_SHIFT);
> @@ -525,12 +551,13 @@ static void pci_bios_map_devices(struct pci_bus *busses)
> pci_config_writew(bdf, PCI_MEMORY_BASE, base>> PCI_MEMORY_SHIFT);
> pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit>> PCI_MEMORY_SHIFT);
>
> - base = s->r[PCI_REGION_TYPE_PREFMEM].base;
> - limit = base + s->r[PCI_REGION_TYPE_PREFMEM].size - 1;
> + type = s->is64 ? PCI_REGION_TYPE_PREFMEM_64 : PCI_REGION_TYPE_PREFMEM;
> + base = s->r[type].base;
> + limit = base + s->r[type].size - 1;
> pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, base>> PCI_PREF_MEMORY_SHIFT);
> pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit>> PCI_PREF_MEMORY_SHIFT);
> - pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
> - pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
> + pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, base>> 32);
> + pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, limit>> 32);
> }
>
> // Map regions on each device.
> --
> 1.7.5.4
>
next prev parent reply other threads:[~2011-12-28 11:41 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-28 4:41 [Qemu-devel] [Seabios] [PATCH 0/3] 64bit PCI BARs allocations Alexey Korolev
2011-12-28 5:00 ` [Qemu-devel] [PATCH 1/3] Add new range above 4GB in _CRS table Alexey Korolev
2011-12-28 5:26 ` [Qemu-devel] [PATCH 2/3] Add a new PCI region type to supports 64 bit ranges Alexey Korolev
2011-12-28 11:30 ` Michael S. Tsirkin
2011-12-29 3:57 ` Alexey Korolev
2011-12-29 2:56 ` Kevin O'Connor
2011-12-29 5:00 ` Alexey Korolev
2011-12-30 5:57 ` Kevin O'Connor
2011-12-29 5:32 ` Alexey Korolev
2011-12-29 16:16 ` Michael S. Tsirkin
2012-01-03 15:14 ` Gerd Hoffmann
2012-01-04 3:10 ` Kevin O'Connor
2011-12-28 5:35 ` [Qemu-devel] [PATCH 3/3] Changes related to secondary buses and 64bit regions Alexey Korolev
2011-12-28 6:30 ` [Qemu-devel] [SeaBIOS] " Alexey Korolev
2011-12-28 11:43 ` Michael S. Tsirkin [this message]
2011-12-29 5:40 ` [Qemu-devel] " Alexey Korolev
2011-12-29 16:18 ` Michael S. Tsirkin
2011-12-30 4:56 ` Alexey Korolev
2011-12-29 5:41 ` Alexey Korolev
2011-12-29 16:19 ` Michael S. Tsirkin
2011-12-29 16:21 ` Michael S. Tsirkin
2011-12-30 5:10 ` Alexey Korolev
2011-12-30 6:02 ` Kevin O'Connor
2011-12-30 5:10 ` Alexey Korolev
2011-12-30 6:22 ` Kevin O'Connor
2011-12-30 7:05 ` Alexey Korolev
2011-12-30 5:03 ` Kevin O'Connor
2011-12-28 11:43 ` [Qemu-devel] [Seabios] [PATCH 0/3] 64bit PCI BARs allocations Michael S. Tsirkin
2011-12-29 9:20 ` Alexey Korolev
2011-12-29 16:21 ` Michael S. Tsirkin
2011-12-29 22:17 ` Alexey Korolev
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=20111228114302.GB26310@redhat.com \
--to=mst@redhat.com \
--cc=alexey.korolev@endace.com \
--cc=qemu-devel@nongnu.org \
--cc=seabios@seabios.org \
--cc=sfd@endace.com \
--cc=yamahata@valinux.co.jp \
/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).