On 11 March 2016 at 18:47, Laszlo Ersek <ler...@redhat.com> wrote:
> On 03/11/16 03:53, Ard Biesheuvel wrote:
>> Unlike Linux on x86, which typically honors the PCI configuration performed
>> by the firmware, Linux on ARM assumes that the PCI subsystem needs to be
>> configured from scratch. This is not entirely unreasonable given the
>> historical background of embedded systems using very basic bootloaders,
>> but is no longer tenable with Linux on arm64 moving to UEFI and ACPI in the
>> server space. For this reason, PCI support in the arm64 kernel running under
>> ACPI is likely to move to the x86 model of honoring the PCI configuration
>> done by the firmware.
>>
>> So let's align with that in our DT based configuration as well, and set the
>> /chosen/linux,pci-probe-only property to 1 in the Device Tree before we
>> hand it to the OS.
>>
>> In case we are exposing an emulated VGA PCI device to the guest, which may
>> subsequently get exposed via the Graphics Output protocol and driven as an
>> efifb by the OS, this ensures the PCI resource allocations for the 
>> framebuffer
>> are not overridden, since that would cause the framebuffer to stop working.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
>> ---
>>  ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c | 23 +++++++++++++++++++-
>>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> The commit message is very clear, thanks for that.
>
>> diff --git a/ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c 
>> b/ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
>> index 74f80d1d2b78..36484a0bbb7e 100644
>> --- a/ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
>> +++ b/ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
>> @@ -286,6 +286,7 @@ InitializeVirtFdtDxe (
>>    VOID                           *DeviceTreeBase;
>>    INT32                          Node, Prev;
>>    INT32                          RtcNode;
>> +  INT32                          ChosenNode;
>>    EFI_STATUS                     Status;
>>    CONST CHAR8                    *Type;
>>    INT32                          Len;
>> @@ -356,8 +357,28 @@ InitializeVirtFdtDxe (
>>        ASSERT (Len == 2 * sizeof (UINT64));
>>        Status = ProcessPciHost (DeviceTreeBase, Node, RegProp);
>>        ASSERT_EFI_ERROR (Status);
>> -      break;
>>
>> +      //
>> +      // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI
>> +      // setup we will perform in the firmware is honored by the Linux OS,
>> +      // rather than torn down and done from scratch. This is generally a 
>> more
>> +      // sensible approach, and aligns with what ACPI based OSes do in 
>> general.
>> +      //
>> +      // In case we are exposing an emulated VGA PCI device to the guest, 
>> which
>> +      // may subsequently get exposed via the Graphics Output protocol and
>> +      // driven as an efifb by Linux, we need this setting to prevent the
>> +      // framebuffer from becoming unresponsive.
>> +      //
>> +      ChosenNode = fdt_path_offset (DeviceTreeBase, "/chosen");
>> +      if (ChosenNode < 0) {
>> +        ChosenNode = fdt_add_subnode (DeviceTreeBase, 0, "/chosen");
>> +      }
>> +      if (ChosenNode < 0) {
>> +        DEBUG ((EFI_D_WARN, "Failed to set /chosen/linux,pci-probe-only 
>> property"));
>> +        break;
>> +      }
>> +      fdt_setprop_u32 (DeviceTreeBase, ChosenNode, "linux,pci-probe-only", 
>> 1);
>> +      break;
>>      case PropertyTypeFwCfg:
>>        ASSERT (Len == 2 * sizeof (UINT64));
>
> Can you please move this logic out of the loop? I reviewed the
> documentation for fdt_add_subnode() and fdt_setprop_u32(), and they can
> both insert new data in the device tree, changing the offsets of some
> existing nodes.
>
> Theoretically, this could mean that the offset of the current node
> changes, and then the Prev = Node; fdt_next_node (... Prev ... )
> sequence might not work. Without the libfdt header giving more specific
> guarantees, I think we should keep all modifications of the device tree
> out of the loop body -- the iteration should be read only.
>
> There is already an example for this, the modification of the RTC node
> near the end of the function. In order to constrain the logic to the
> case when a PCI host node is present, you could introduce a boolean flag
> (to be set under the case label), or even compare
> PcdPciExpressBaseAddress against zero (it is set by ProcessPciHost()).
>
> ... Actually, since the loop caches the RtcNode offset as well, that's
> another thing that could break if we inserted nodes or properties during
> the iteration. So this manipulation has to happen after disabling the
> RTC -- looking up /chosen from scratch will work fine even then.
>

Ah yes, how sloppy of me. I will just add a boolean, and move this
code to the end of the function.

Thanks,
Ard.
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to