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(-)
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; } }
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)) {
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);
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,
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);
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;
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 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 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 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
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