]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg/PciHostBridge: Move declaration of mIoMmu to header file
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
index 1494848c3e8c5a256a5c6a1242fee7352795d954..a74c6f0d30b8b0b48fb67e02d05603cec890c096 100644 (file)
@@ -2,7 +2,7 @@
 \r
   Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
 \r
-Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -17,8 +17,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "PciRootBridge.h"\r
 #include "PciHostResource.h"\r
 \r
-\r
-EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
 EFI_CPU_IO2_PROTOCOL        *mCpuIo;\r
 \r
 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
@@ -28,10 +26,43 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
   L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
 };\r
 \r
-EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;\r
+EDKII_IOMMU_PROTOCOL        *mIoMmu;\r
 EFI_EVENT                   mIoMmuEvent;\r
 VOID                        *mIoMmuRegistration;\r
 \r
+/**\r
+  This routine gets translation offset from a root bridge instance by resource type.\r
+\r
+  @param RootBridge The Root Bridge Instance for the resources.\r
+  @param ResourceType The Resource Type of the translation offset.\r
+\r
+  @retval The Translation Offset of the specified resource.\r
+**/\r
+UINT64\r
+GetTranslationByResourceType (\r
+  IN  PCI_ROOT_BRIDGE_INSTANCE     *RootBridge,\r
+  IN  PCI_RESOURCE_TYPE            ResourceType\r
+  )\r
+{\r
+  switch (ResourceType) {\r
+    case TypeIo:\r
+      return RootBridge->Io.Translation;\r
+    case TypeMem32:\r
+      return RootBridge->Mem.Translation;\r
+    case TypePMem32:\r
+      return RootBridge->PMem.Translation;\r
+    case TypeMem64:\r
+      return RootBridge->MemAbove4G.Translation;\r
+    case TypePMem64:\r
+      return RootBridge->PMemAbove4G.Translation;\r
+    case TypeBus:\r
+      return RootBridge->Bus.Translation;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return 0;\r
+  }\r
+}\r
+\r
 /**\r
   Ensure the compatibility of an IO space descriptor with the IO aperture.\r
 \r
@@ -332,7 +363,7 @@ IoMmuProtocolCallback (
 {\r
   EFI_STATUS   Status;\r
 \r
-  Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);\r
+  Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);\r
   if (!EFI_ERROR(Status)) {\r
     gBS->CloseEvent (mIoMmuEvent);\r
   }\r
@@ -366,14 +397,13 @@ InitializePciHostBridge (
   UINTN                       MemApertureIndex;\r
   BOOLEAN                     ResourceAssigned;\r
   LIST_ENTRY                  *Link;\r
+  UINT64                      HostAddress;\r
 \r
   RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
   if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);\r
-  ASSERT_EFI_ERROR (Status);\r
   Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -411,8 +441,15 @@ InitializePciHostBridge (
     }\r
 \r
     if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {\r
+      //\r
+      // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
+      // For GCD resource manipulation, we need to use host address.\r
+      //\r
+      HostAddress = TO_HOST_ADDRESS (RootBridges[Index].Io.Base,\r
+        RootBridges[Index].Io.Translation);\r
+\r
       Status = AddIoSpace (\r
-                 RootBridges[Index].Io.Base,\r
+                 HostAddress,\r
                  RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
                  );\r
       ASSERT_EFI_ERROR (Status);\r
@@ -422,7 +459,7 @@ InitializePciHostBridge (
                         EfiGcdIoTypeIo,\r
                         0,\r
                         RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,\r
-                        &RootBridges[Index].Io.Base,\r
+                        &HostAddress,\r
                         gImageHandle,\r
                         NULL\r
                         );\r
@@ -443,14 +480,20 @@ InitializePciHostBridge (
 \r
     for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {\r
       if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {\r
+        //\r
+        // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
+        // For GCD resource manipulation, we need to use host address.\r
+        //\r
+        HostAddress = TO_HOST_ADDRESS (MemApertures[MemApertureIndex]->Base,\r
+          MemApertures[MemApertureIndex]->Translation);\r
         Status = AddMemoryMappedIoSpace (\r
-                   MemApertures[MemApertureIndex]->Base,\r
+                   HostAddress,\r
                    MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
                    EFI_MEMORY_UC\r
                    );\r
         ASSERT_EFI_ERROR (Status);\r
         Status = gDS->SetMemorySpaceAttributes (\r
-                        MemApertures[MemApertureIndex]->Base,\r
+                        HostAddress,\r
                         MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
                         EFI_MEMORY_UC\r
                         );\r
@@ -463,7 +506,7 @@ InitializePciHostBridge (
                           EfiGcdMemoryTypeMemoryMappedIo,\r
                           0,\r
                           MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
-                          &MemApertures[MemApertureIndex]->Base,\r
+                          &HostAddress,\r
                           gImageHandle,\r
                           NULL\r
                           );\r
@@ -654,6 +697,11 @@ AllocateResource (
   if (BaseAddress < Limit) {\r
     //\r
     // Have to make sure Aligment is handled since we are doing direct address allocation\r
+    // Strictly speaking, alignment requirement should be applied to device\r
+    // address instead of host address which is used in GCD manipulation below,\r
+    // but as we restrict the alignment of Translation to be larger than any BAR\r
+    // alignment in the root bridge, we can simplify the situation and consider\r
+    // the same alignment requirement is also applied to host address.\r
     //\r
     BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
 \r
@@ -721,6 +769,7 @@ NotifyPhase (
   PCI_RESOURCE_TYPE                     Index2;\r
   BOOLEAN                               ResNodeHandled[TypeMax];\r
   UINT64                                MaxAlignment;\r
+  UINT64                                Translation;\r
 \r
   HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
 \r
@@ -822,14 +871,43 @@ NotifyPhase (
           BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
           BaseAddress = MAX_UINT64;\r
 \r
+          //\r
+          // RESTRICTION: To simplify the situation, we require the alignment of\r
+          // Translation must be larger than any BAR alignment in the same root\r
+          // bridge, so that resource allocation alignment can be applied to\r
+          // both device address and host address.\r
+          //\r
+          Translation = GetTranslationByResourceType (RootBridge, Index);\r
+          if ((Translation & Alignment) != 0) {\r
+            DEBUG ((DEBUG_ERROR, "[%a:%d] Translation %lx is not aligned to %lx!\n",\r
+              __FUNCTION__, __LINE__, Translation, Alignment\r
+              ));\r
+            ASSERT ((Translation & Alignment) == 0);\r
+            //\r
+            // This may be caused by too large alignment or too small\r
+            // Translation; pick the 1st possibility and return out of resource,\r
+            // which can also go thru the same process for out of resource\r
+            // outside the loop.\r
+            //\r
+            ReturnStatus = EFI_OUT_OF_RESOURCES;\r
+            continue;\r
+          }\r
+\r
           switch (Index) {\r
           case TypeIo:\r
+            //\r
+            // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
+            // For AllocateResource is manipulating GCD resource, we need to use\r
+            // host address here.\r
+            //\r
             BaseAddress = AllocateResource (\r
                             FALSE,\r
                             RootBridge->ResAllocNode[Index].Length,\r
                             MIN (15, BitsOfAlignment),\r
-                            ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
-                            RootBridge->Io.Limit\r
+                            TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
+                              RootBridge->Io.Translation),\r
+                            TO_HOST_ADDRESS (RootBridge->Io.Limit,\r
+                              RootBridge->Io.Translation)\r
                             );\r
             break;\r
 \r
@@ -838,8 +916,10 @@ NotifyPhase (
                             TRUE,\r
                             RootBridge->ResAllocNode[Index].Length,\r
                             MIN (63, BitsOfAlignment),\r
-                            ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
-                            RootBridge->MemAbove4G.Limit\r
+                            TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
+                              RootBridge->MemAbove4G.Translation),\r
+                            TO_HOST_ADDRESS (RootBridge->MemAbove4G.Limit,\r
+                              RootBridge->MemAbove4G.Translation)\r
                             );\r
             if (BaseAddress != MAX_UINT64) {\r
               break;\r
@@ -853,8 +933,10 @@ NotifyPhase (
                             TRUE,\r
                             RootBridge->ResAllocNode[Index].Length,\r
                             MIN (31, BitsOfAlignment),\r
-                            ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
-                            RootBridge->Mem.Limit\r
+                            TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
+                              RootBridge->Mem.Translation),\r
+                            TO_HOST_ADDRESS (RootBridge->Mem.Limit,\r
+                              RootBridge->Mem.Translation)\r
                             );\r
             break;\r
 \r
@@ -863,8 +945,10 @@ NotifyPhase (
                             TRUE,\r
                             RootBridge->ResAllocNode[Index].Length,\r
                             MIN (63, BitsOfAlignment),\r
-                            ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
-                            RootBridge->PMemAbove4G.Limit\r
+                            TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
+                              RootBridge->PMemAbove4G.Translation),\r
+                            TO_HOST_ADDRESS (RootBridge->PMemAbove4G.Limit,\r
+                              RootBridge->PMemAbove4G.Translation)\r
                             );\r
             if (BaseAddress != MAX_UINT64) {\r
               break;\r
@@ -877,8 +961,10 @@ NotifyPhase (
                             TRUE,\r
                             RootBridge->ResAllocNode[Index].Length,\r
                             MIN (31, BitsOfAlignment),\r
-                            ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
-                            RootBridge->PMem.Limit\r
+                            TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
+                              RootBridge->PMem.Translation),\r
+                            TO_HOST_ADDRESS (RootBridge->PMem.Limit,\r
+                              RootBridge->PMem.Translation)\r
                             );\r
             break;\r
 \r
@@ -1421,7 +1507,14 @@ GetProposedResources (
           Descriptor->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
           Descriptor->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
           Descriptor->GenFlag               = 0;\r
-          Descriptor->AddrRangeMin          = RootBridge->ResAllocNode[Index].Base;\r
+          //\r
+          // AddrRangeMin in Resource Descriptor here should be device address\r
+          // instead of host address, or else PCI bus driver cannot set correct\r
+          // address into PCI BAR registers.\r
+          // Base in ResAllocNode is a host address, so conversion is needed.\r
+          //\r
+          Descriptor->AddrRangeMin          = TO_DEVICE_ADDRESS (RootBridge->ResAllocNode[Index].Base,\r
+            GetTranslationByResourceType (RootBridge, Index));\r
           Descriptor->AddrRangeMax          = 0;\r
           Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
           Descriptor->AddrLen               = RootBridge->ResAllocNode[Index].Length;\r