Hi,
It looks I've found the root of the problem
This piece of code in pciinit.c may cause overlap of RAM and pci64 resource
window.
pcimem64_start = (RamSizeOver4G + pcimem64_size) & ~(pcimem64_size-1);
Here is a part of the log showing the problem
..................
Find memory size
Ram Size=0xe0000000 (0x0000000120000000 high)
..........................
Found 9 PCI devices (max PCI bus is 00)
=== PCI new allocation pass #1 ===
PCI: check devices
=== PCI new allocation pass #2 ===
RAM OVER 4GB: 0x120000000 pcimem64 size: 0x100000000
pcimem64_start 0x200000000 pcimem64_end: 0x300000000
PCI: map device bdf=00:04.0 bar 2, addr 200000000, size 10000000 [prefmem]
PCI: map device bdf=00:05.0 bar 2, addr 210000000, size 10000000 [prefmem]
PCI: map device bdf=00:01.2 bar 4, addr 0000c000, size 00000020 [io]
I guess it would be proper if pcimem64_start will be set in this way:
pcimem64_start = ALIGN(0x100000000LL + RamSizeOver4G, pcimem64_size);
The patch 6/6 with the fix is attached...
P/S :
While debugging of this issue I've noticed yet another possible problem.
I've added a debug output of P(S|L|E)32 and P(S|L|E)64 registers to
acpi-dsdt.dsl file
In case of static allocation of _CRS method (an old way) we have:
PS32: 0xE0000000
PE32: 0xFEBFFFFF
PL32: 0x1EC00000
PS64: 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00
PE64: 0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00
PL64: 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00
In case of dynamic allocation of _CRS method (a new way) we have:
PS32: 0xE0000000
PE32: 0xFEBFFFFF
PL32: 0x1EBFFFFF
PS64: 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00
PE64: 0xFF,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00
PL64: 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00
Probably the correct value of the length of the PCI resource window should be
set as
len = pcimem_end - pcimem_start?
In new implementation it is:
+ pcimem[0] = pcimem_start;
+ pcimem[1] = pcimem_end - 1;
+ pcimem[2] = pcimem_end - pcimem_start - 1;
+ pcimem[3] = pcimem64_start;
+ pcimem[4] = pcimem64_end - 1;
+ pcimem[5] = pcimem64_end - pcimem64_start - 1;
diff --git a/src/pciinit.c b/src/pciinit.c
index c1d932a..1acd55f 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -591,6 +591,11 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
static void pci_bios_map_devices(struct pci_bus *busses)
{
+ u64 pcimem64_size;
+ int shift;
+
+ pcimem_start = RamSize;
+
if (pci_bios_init_root_regions(busses)) {
struct pci_region r64_mem, r64_pref;
r64_mem.list = NULL;
@@ -603,14 +608,26 @@ static void pci_bios_map_devices(struct pci_bus *busses)
if (pci_bios_init_root_regions(busses))
panic("PCI: out of 32bit address space\n");
- r64_mem.base = pcimem64_start;
- u64 sum = pci_region_sum(&r64_mem);
- u64 align = pci_region_align(&r64_pref);
- r64_pref.base = ALIGN(r64_mem.base + sum, align);
+ // try 4 GB ... 512 GB
+ for (shift = 32; shift < 39; shift++) {
+ pcimem64_size = (1LL << shift);
+ pcimem64_start = ALIGN(0x100000000LL + RamSizeOver4G, pcimem64_size);
+ pcimem64_end = pcimem64_start + pcimem64_size;
+
+ r64_mem.base = pcimem64_start;
+ u64 sum = pci_region_sum(&r64_mem);
+ u64 align = pci_region_align(&r64_pref);
+ r64_pref.base = ALIGN(r64_mem.base + sum, align);
+ if (r64_pref.base + pci_region_sum(&r64_pref) <= pcimem64_end)
+ break;
+ }
if (r64_pref.base + pci_region_sum(&r64_pref) > pcimem64_end)
panic("PCI: out of 64bit address space\n");
pci_region_map_entries(busses, &r64_mem);
pci_region_map_entries(busses, &r64_pref);
+ } else {
+ // no bars mapped high -> drop 64bit window (see dsdt)
+ pcimem64_start = 0;
}
// Map regions on each device.
int bus;
_______________________________________________
SeaBIOS mailing list
[email protected]
http://www.seabios.org/mailman/listinfo/seabios