On 2020/12/11 18:57, Ni, Ray wrote:
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Jiahui Cen via groups.io
Sent: Friday, December 4, 2020 2:49 PM
To: devel@edk2.groups.io; lersek@...
Cc: Justen, Jordan L <jordan.l.justen@...>; ard.biesheuvel@...; leif@...; xieyingtai@...;
miaoyubo@...; xuxiaoyang2@...
Subject: Re: [edk2-devel] [PATCH v2 0/4] Add extra pci roots support for Arm
Hi Laszlo,
During the modification of this patch series, I got a confusing problem
that the EDK2's Alignment seems not fit with Linux on ARM.
EDK2, in CalculateResourceAperture, aligns the offset of child nodes
in descending order and uses the *Bridge's alignment* to align the
total length of Bridge.
However, Linux, in pbus_size_mem, would align the size of child nodes
and use *the half of max alignment of child nodes* to align the total
length of Bridge.
eg. A Root Bridge with Bus [d2]
-+-[0000:d2]---01.0-[d3]----01.0
where [d2:01.00] is a pcie-pci-bridge with BAR0 (mem, 64-bit, non-pref) [size=256]
[d3:01.00] is a PCI Device with BAR0 (mem, 64-bit, pref) [size=128K]
BAR4 (mem, 64-bit, pref) [size=64M]
In EDK2, the Resource Map would be:
PciBus: Resource Map for Root Bridge PciRoot(0xD2)
Type = Mem64; Base = 0x8004000000; Length = 0x4200000; Alignment = 0x3FFFFFF
Base = 0x8004000000; Length = 0x4100000; Alignment = 0x3FFFFFF; Owner = PPB [D2|01|00:**]; Type = PMem64
Base = 0x8008100000; Length = 0x100; Alignment = 0xFFF; Owner = PPB [D2|01|00:10]
PciBus: Resource Map for Bridge [D2|01|00]
Type = PMem64; Base = 0x8004000000; Length = 0x4100000; Alignment = 0x3FFFFFF
Base = 0x8004000000; Length = 0x4000000; Alignment = 0x3FFFFFF; Owner = PCI [D3|01|00:20]
Base = 0x8008000000; Length = 0x20000; Alignment = 0x1FFFF; Owner = PCI [D3|01|00:10]
Type = Mem64; Base = 0x8008100000; Length = 0x100; Alignment = 0xFFF
It shows that with EDK2's alignment [d2:01.00] only requires
a PMem64 resource range of 0x4100000.
However in Linux, [d2:01.00]'s BAR14 (Prefetchable Memory
Resource behind the Bridge) requires a PMem64 resource range
of 0x06000000, which comes from (0x4000000 + 0x20000) with
alignment=0x1FFFFFF the half of the max alignment 0x3FFFFFF.
How is 0x3FFFFFF calculated?
0x3FFFFFF = 0x8000000 / 2 - 1, and 0x8000000 is the minimum value that's
power of 2 and bigger than 0x6000000. Is my understanding correct?
The bridge has 2 resource alignments, 0x4000000 with order 26 and 0x20000
with order 20 (the minimum order is 20). Order 26 is the maximum value
whose alignment is larger than the sum of alignments with order below it.
The final alignment is 0x2000000 = 0x4000000 / 2, and the final size is
0x6000000 = ALIGN(0x4000000 + 0x20000, 0x2000000).
It seems that Kernel tries to use a suitable alignment that ensures the
final size can fit all the resource requirements under the bridge, rather
than place each resource and calculate the exact size. Therefore, the size
may be larger than needed.
I don't understand why this calculation method is chosen.
It seems a kernel bug to me.
I thought Linux doesn't handle the pci resource assignment but just use what was
assigned by firmware.
For x86, Linux does not handle the pci resource assignment. But for arm, it
would assign all the pci resources, unless we explicitly let Linux preserve
PCI resource alignment made by firmware, using "PCI Boot Configuration"
_DSM function.
What do you think of adding "PCI Boot Configuration" _DSM function into
dsdt table to make kernel use firmware's resource configuration?
Thanks,
Jiahui
Furthermore, Linux Kernel will treat pcie-root-port as a hotplugable
bridge and try to require more resource. But EDK2 seems not support
hotplug padding for ARM?
Hotplug padding is supported through HotPlugInit protocol in edk2.