]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtPkg/VirtFdtDxe: set /chosen/linux,pci-probe-only to 1 in DTB
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 10 Mar 2016 10:36:31 +0000 (17:36 +0700)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 11 Mar 2016 12:32:44 +0000 (19:32 +0700)
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.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c

index 74f80d1d2b78bc30c1e2a56eb3e15b688f4b31a2..437b2a8792160626d826970bde84d6c8da67db4d 100644 (file)
@@ -304,6 +304,7 @@ InitializeVirtFdtDxe (
   UINT64                         FwCfgDataSize;\r
   UINT64                         FwCfgDmaAddress;\r
   UINT64                         FwCfgDmaSize;\r
   UINT64                         FwCfgDataSize;\r
   UINT64                         FwCfgDmaAddress;\r
   UINT64                         FwCfgDmaSize;\r
+  BOOLEAN                        HavePci;\r
 \r
   Hob = GetFirstGuidHob(&gFdtHobGuid);\r
   if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
 \r
   Hob = GetFirstGuidHob(&gFdtHobGuid);\r
   if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
@@ -322,6 +323,7 @@ InitializeVirtFdtDxe (
   DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
 \r
   RtcNode = -1;\r
   DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
 \r
   RtcNode = -1;\r
+  HavePci = FALSE;\r
   //\r
   // Now enumerate the nodes and install peripherals that we are interested in,\r
   // i.e., GIC, RTC and virtio MMIO nodes\r
   //\r
   // Now enumerate the nodes and install peripherals that we are interested in,\r
   // i.e., GIC, RTC and virtio MMIO nodes\r
@@ -356,6 +358,7 @@ InitializeVirtFdtDxe (
       ASSERT (Len == 2 * sizeof (UINT64));\r
       Status = ProcessPciHost (DeviceTreeBase, Node, RegProp);\r
       ASSERT_EFI_ERROR (Status);\r
       ASSERT (Len == 2 * sizeof (UINT64));\r
       Status = ProcessPciHost (DeviceTreeBase, Node, RegProp);\r
       ASSERT_EFI_ERROR (Status);\r
+      HavePci = TRUE;\r
       break;\r
 \r
     case PropertyTypeFwCfg:\r
       break;\r
 \r
     case PropertyTypeFwCfg:\r
@@ -579,5 +582,28 @@ InitializeVirtFdtDxe (
         "disabled") != 0) {\r
     DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));\r
   }\r
         "disabled") != 0) {\r
     DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));\r
   }\r
+\r
+  if (HavePci) {\r
+    //\r
+    // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI\r
+    // setup we will perform in the firmware is honored by the Linux OS,\r
+    // rather than torn down and done from scratch. This is generally a more\r
+    // sensible approach, and aligns with what ACPI based OSes do in general.\r
+    //\r
+    // In case we are exposing an emulated VGA PCI device to the guest, which\r
+    // may subsequently get exposed via the Graphics Output protocol and\r
+    // driven as an efifb by Linux, we need this setting to prevent the\r
+    // framebuffer from becoming unresponsive.\r
+    //\r
+    Node = fdt_path_offset (DeviceTreeBase, "/chosen");\r
+    if (Node < 0) {\r
+      Node = fdt_add_subnode (DeviceTreeBase, 0, "/chosen");\r
+    }\r
+    if (Node < 0 ||\r
+        fdt_setprop_u32 (DeviceTreeBase, Node, "linux,pci-probe-only", 1) < 0) {\r
+      DEBUG ((EFI_D_WARN, "Failed to set /chosen/linux,pci-probe-only property\n"));\r
+    }\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
   return EFI_SUCCESS;\r
 }\r