[PATCH 0/6] pci patches
Hi, Here is a collection of pci patches. The first two go clearly into the bugfix category. Next two improve alignment a bit. Patch 5 adds some debug logging. Patch 6 adds etc/reserved-memory-end support. cheers, Gerd Gerd Hoffmann (6): pci: don't reorder entries when moving to 64bit list pci: don't map usb host adapters above 4G pci: align 64bit pci regions to 1G pci: tweak + comment minimum allocations pci: log pci windows pci: map 64-bit BARs at location provided by emulator src/fw/pciinit.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) -- 1.8.3.1
Otherwise the 64bit bars are not mapped in largest first order, thereby messing up the alignment. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 34279a4..84bb65b 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -574,14 +574,19 @@ static u64 pci_region_sum(struct pci_region *r) static void pci_region_migrate_64bit_entries(struct pci_region *from, struct pci_region *to) { - struct hlist_node *n, **last = &to->list.first; + struct hlist_node *n, *last = NULL; struct pci_region_entry *entry; hlist_for_each_entry_safe(entry, n, &from->list, node) { if (!entry->is64) continue; // Move from source list to destination list. hlist_del(&entry->node); - hlist_add(&entry->node, last); + if (hlist_empty(&to->list)) { + hlist_add_head(&entry->node, &to->list); + } else { + hlist_add_after(&entry->node, last); + } + last = &entry->node; } } -- 1.8.3.1
On Tue, Nov 26, 2013 at 01:24:09PM +0100, Gerd Hoffmann wrote:
Otherwise the 64bit bars are not mapped in largest first order, thereby messing up the alignment.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 34279a4..84bb65b 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -574,14 +574,19 @@ static u64 pci_region_sum(struct pci_region *r) static void pci_region_migrate_64bit_entries(struct pci_region *from, struct pci_region *to) { - struct hlist_node *n, **last = &to->list.first; + struct hlist_node *n, *last = NULL; struct pci_region_entry *entry; hlist_for_each_entry_safe(entry, n, &from->list, node) { if (!entry->is64) continue; // Move from source list to destination list. hlist_del(&entry->node); - hlist_add(&entry->node, last); + if (hlist_empty(&to->list)) { + hlist_add_head(&entry->node, &to->list); + } else { + hlist_add_after(&entry->node, last); + } + last = &entry->node;
This could be done by just adding: last = &entry->node.next; However, this pattern seems to be common in the code and hard to follow, so maybe a new macro should be added and the code refactored to be more like what you have. -Kevin
On Di, 2013-11-26 at 22:03 -0500, Kevin O'Connor wrote:
On Tue, Nov 26, 2013 at 01:24:09PM +0100, Gerd Hoffmann wrote:
Otherwise the 64bit bars are not mapped in largest first order, thereby messing up the alignment.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 34279a4..84bb65b 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -574,14 +574,19 @@ static u64 pci_region_sum(struct pci_region *r) static void pci_region_migrate_64bit_entries(struct pci_region *from, struct pci_region *to) { - struct hlist_node *n, **last = &to->list.first; + struct hlist_node *n, *last = NULL; struct pci_region_entry *entry; hlist_for_each_entry_safe(entry, n, &from->list, node) { if (!entry->is64) continue; // Move from source list to destination list. hlist_del(&entry->node); - hlist_add(&entry->node, last); + if (hlist_empty(&to->list)) { + hlist_add_head(&entry->node, &to->list); + } else { + hlist_add_after(&entry->node, last); + } + last = &entry->node;
This could be done by just adding: last = &entry->node.next;
Ok, I'll do it this way. cheers, Gerd
Otherwise our xhci driver has trouble accessing the mmio registers. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 84bb65b..1d5e919 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -579,6 +579,8 @@ static void pci_region_migrate_64bit_entries(struct pci_region *from, hlist_for_each_entry_safe(entry, n, &from->list, node) { if (!entry->is64) continue; + if (entry->dev->class == PCI_CLASS_SERIAL_USB) + continue; // Move from source list to destination list. hlist_del(&entry->node); if (hlist_empty(&to->list)) { -- 1.8.3.1
So they are hugepage aligned. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 1d5e919..1fd02f0 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -787,10 +787,15 @@ static void pci_bios_map_devices(struct pci_bus *busses) u64 align_mem = pci_region_align(&r64_mem); u64 align_pref = pci_region_align(&r64_pref); - r64_mem.base = ALIGN(0x100000000LL + RamSizeOver4G, align_mem); - r64_pref.base = ALIGN(r64_mem.base + sum_mem, align_pref); + r64_mem.base = 0x100000000LL + RamSizeOver4G; + r64_mem.base = ALIGN(r64_mem.base, align_mem); + r64_mem.base = ALIGN(r64_mem.base, (1LL<<30)); // 1G hugepage + r64_pref.base = r64_mem.base + sum_mem; + r64_pref.base = ALIGN(r64_pref.base, align_pref); + r64_pref.base = ALIGN(r64_pref.base, (1LL<<30)); // 1G hugepage pcimem64_start = r64_mem.base; pcimem64_end = r64_pref.base + sum_pref; + pcimem64_end = ALIGN(pcimem64_end, (1LL<<30)); // 1G hugepage pci_region_map_entries(busses, &r64_mem); pci_region_map_entries(busses, &r64_pref); -- 1.8.3.1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 1fd02f0..23fbd2f 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -20,9 +20,9 @@ #include "util.h" // pci_setup #include "x86.h" // outb -#define PCI_DEVICE_MEM_MIN 0x1000 -#define PCI_BRIDGE_IO_MIN 0x1000 -#define PCI_BRIDGE_MEM_MIN 0x100000 +#define PCI_DEVICE_MEM_MIN (1<<12) // 4k == page size +#define PCI_BRIDGE_MEM_MIN (1<<21) // 2M == hugepage size +#define PCI_BRIDGE_IO_MIN 0x1000 // mandated by pci bridge spec enum pci_region_type { PCI_REGION_TYPE_IO, -- 1.8.3.1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 23fbd2f..3de0c7e 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -770,6 +770,7 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r) static void pci_bios_map_devices(struct pci_bus *busses) { + dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end); if (pci_bios_init_root_regions(busses)) { struct pci_region r64_mem, r64_pref; r64_mem.list.first = NULL; @@ -796,6 +797,7 @@ static void pci_bios_map_devices(struct pci_bus *busses) pcimem64_start = r64_mem.base; pcimem64_end = r64_pref.base + sum_pref; pcimem64_end = ALIGN(pcimem64_end, (1LL<<30)); // 1G hugepage + dprintf(1, "PCI: 64: %016llx - %016llx\n", pcimem64_start, pcimem64_end); pci_region_map_entries(busses, &r64_mem); pci_region_map_entries(busses, &r64_pref); -- 1.8.3.1
Currently 64-bit PCI BARs are unconditionally mapped by BIOS right over 4G + RamSizeOver4G location, which doesn't allow to reserve extra space before 64-bit PCI window. For memory hotplug an extra RAM space might be reserved after present 64-bit RAM end and BIOS should map 64-bit PCI BARs after it. Introduce "etc/reserved-memory-end" romfile to provide BIOS a hint where it should start mapping of 64-bit PCI BARs. If romfile is missing, BIOS reverts to legacy behavior and starts mapping after high memory. Based-on-patch-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 3de0c7e..654697d 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -19,6 +19,8 @@ #include "string.h" // memset #include "util.h" // pci_setup #include "x86.h" // outb +#include "byteorder.h" // le64_to_cpu +#include "romfile.h" // romfile_loadint #define PCI_DEVICE_MEM_MIN (1<<12) // 4k == page size #define PCI_BRIDGE_MEM_MIN (1<<21) // 2M == hugepage size @@ -788,7 +790,9 @@ static void pci_bios_map_devices(struct pci_bus *busses) u64 align_mem = pci_region_align(&r64_mem); u64 align_pref = pci_region_align(&r64_pref); - r64_mem.base = 0x100000000LL + RamSizeOver4G; + r64_mem.base = le64_to_cpu(romfile_loadint("etc/reserved-memory-end", 0)); + if (r64_mem.base < 0x100000000LL + RamSizeOver4G) + r64_mem.base = 0x100000000LL + RamSizeOver4G; r64_mem.base = ALIGN(r64_mem.base, align_mem); r64_mem.base = ALIGN(r64_mem.base, (1LL<<30)); // 1G hugepage r64_pref.base = r64_mem.base + sum_mem; -- 1.8.3.1
On Tue, 26 Nov 2013 13:24:14 +0100 Gerd Hoffmann <kraxel@redhat.com> wrote:
Currently 64-bit PCI BARs are unconditionally mapped by BIOS right over 4G + RamSizeOver4G location, which doesn't allow to reserve extra space before 64-bit PCI window. For memory hotplug an extra RAM space might be reserved after present 64-bit RAM end and BIOS should map 64-bit PCI BARs after it.
Introduce "etc/reserved-memory-end" romfile to provide BIOS a hint where it should start mapping of 64-bit PCI BARs. If romfile is missing, BIOS reverts to legacy behavior and starts mapping after high memory.
Based-on-patch-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- src/fw/pciinit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 3de0c7e..654697d 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -19,6 +19,8 @@ #include "string.h" // memset #include "util.h" // pci_setup #include "x86.h" // outb +#include "byteorder.h" // le64_to_cpu +#include "romfile.h" // romfile_loadint
#define PCI_DEVICE_MEM_MIN (1<<12) // 4k == page size #define PCI_BRIDGE_MEM_MIN (1<<21) // 2M == hugepage size @@ -788,7 +790,9 @@ static void pci_bios_map_devices(struct pci_bus *busses) u64 align_mem = pci_region_align(&r64_mem); u64 align_pref = pci_region_align(&r64_pref);
- r64_mem.base = 0x100000000LL + RamSizeOver4G; + r64_mem.base = le64_to_cpu(romfile_loadint("etc/reserved-memory-end", 0)); + if (r64_mem.base < 0x100000000LL + RamSizeOver4G) + r64_mem.base = 0x100000000LL + RamSizeOver4G; r64_mem.base = ALIGN(r64_mem.base, align_mem); r64_mem.base = ALIGN(r64_mem.base, (1LL<<30)); // 1G hugepage r64_pref.base = r64_mem.base + sum_mem;
Reviewed-By: Igor Mammedov <imammedo@redhat.com>
On Tue, Nov 26, 2013 at 01:24:08PM +0100, Gerd Hoffmann wrote:
Hi,
Here is a collection of pci patches. The first two go clearly into the bugfix category. Next two improve alignment a bit. Patch 5 adds some debug logging. Patch 6 adds etc/reserved-memory-end support.
Looks okay to me. -Kevin
On Di, 2013-11-26 at 13:24 +0100, Gerd Hoffmann wrote:
Hi,
Here is a collection of pci patches. The first two go clearly into the bugfix category. Next two improve alignment a bit. Patch 5 adds some debug logging. Patch 6 adds etc/reserved-memory-end support.
Pushed. Patch #1 updates as discussed. Patch #6 pushed even though the qemu side isn't commited yet. But I want have it in the next release to not make the qemu/seabios sync needless complicated. Patch also hardly harms and is simple enough that we can revert it without trouble in the unlikely event the qemu patch isn't merged. cheers, Gerd
participants (3)
-
Gerd Hoffmann -
Igor Mammedov -
Kevin O'Connor