X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FPciHostBridgeDxe%2FPciRootBridgeIo.c;h=068295b7c0b30edb2996401c7e94acb2d724701e;hp=6a9294d3495b8c54f5acbfa3c11d3b1189ab7cac;hb=c15da8eb3587f2371df330bc4bcb5a31b2efac0d;hpb=ccf660168eac4ca250d2a22cb9a4af504e2cef74 diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c index 6a9294d349..068295b7c0 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c @@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "PciRootBridge.h" #include "PciHostResource.h" +extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; + #define NO_MAPPING (VOID *) (UINTN) -1 // @@ -59,92 +61,97 @@ UINT8 mOutStride[] = { Construct the Pci Root Bridge instance. @param Bridge The root bridge instance. - @param HostBridgeHandle Handle to the HostBridge. @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created or NULL if creation fails. **/ PCI_ROOT_BRIDGE_INSTANCE * CreateRootBridge ( - IN PCI_ROOT_BRIDGE *Bridge, - IN EFI_HANDLE HostBridgeHandle + IN PCI_ROOT_BRIDGE *Bridge ) { PCI_ROOT_BRIDGE_INSTANCE *RootBridge; PCI_RESOURCE_TYPE Index; CHAR16 *DevicePathStr; + PCI_ROOT_BRIDGE_APERTURE *Aperture; DevicePathStr = NULL; DEBUG ((EFI_D_INFO, "RootBridge: ")); DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE))); - DEBUG ((EFI_D_INFO, "Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes)); - DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No")); - DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes, + DEBUG ((EFI_D_INFO, " Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes)); + DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No")); + DEBUG ((EFI_D_INFO, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? L"Yes" : L"No")); + DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes, (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"", (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L"" )); - DEBUG ((EFI_D_INFO, " Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit)); - DEBUG ((EFI_D_INFO, " Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit)); - DEBUG ((EFI_D_INFO, " Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit)); - DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit)); - DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit)); - DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit)); + DEBUG ((EFI_D_INFO, " Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit)); + DEBUG ((EFI_D_INFO, " Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit)); + DEBUG ((EFI_D_INFO, " Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit)); + DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit)); + DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit)); + DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit)); // // Make sure Mem and MemAbove4G apertures are valid // - if (Bridge->Mem.Base < Bridge->Mem.Limit) { + if (Bridge->Mem.Base <= Bridge->Mem.Limit) { ASSERT (Bridge->Mem.Limit < SIZE_4GB); if (Bridge->Mem.Limit >= SIZE_4GB) { return NULL; } } - if (Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) { + if (Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) { ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB); if (Bridge->MemAbove4G.Base < SIZE_4GB) { return NULL; } } - if (Bridge->PMem.Base < Bridge->PMem.Limit) { + if (Bridge->PMem.Base <= Bridge->PMem.Limit) { ASSERT (Bridge->PMem.Limit < SIZE_4GB); if (Bridge->PMem.Limit >= SIZE_4GB) { return NULL; } } - if (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) { + if (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit) { ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB); if (Bridge->PMemAbove4G.Base < SIZE_4GB) { return NULL; } } - if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) { - // - // If this bit is set, then the PCI Root Bridge does not - // support separate windows for Non-prefetchable and Prefetchable - // memory. - // - ASSERT (Bridge->PMem.Base >= Bridge->PMem.Limit); - ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit); - if ((Bridge->PMem.Base < Bridge->PMem.Limit) || - (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) - ) { - return NULL; + // + // Ignore AllocationAttributes when resources were already assigned. + // + if (!Bridge->ResourceAssigned) { + if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) { + // + // If this bit is set, then the PCI Root Bridge does not + // support separate windows for Non-prefetchable and Prefetchable + // memory. + // + ASSERT (Bridge->PMem.Base > Bridge->PMem.Limit); + ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit); + if ((Bridge->PMem.Base <= Bridge->PMem.Limit) || + (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit) + ) { + return NULL; + } } - } - if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) { - // - // If this bit is not set, then the PCI Root Bridge does not support - // 64 bit memory windows. - // - ASSERT (Bridge->MemAbove4G.Base >= Bridge->MemAbove4G.Limit); - ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit); - if ((Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) || - (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) - ) { - return NULL; + if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) { + // + // If this bit is not set, then the PCI Root Bridge does not support + // 64 bit memory windows. + // + ASSERT (Bridge->MemAbove4G.Base > Bridge->MemAbove4G.Limit); + ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit); + if ((Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) || + (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit) + ) { + return NULL; + } } } @@ -155,6 +162,7 @@ CreateRootBridge ( RootBridge->Supports = Bridge->Supports; RootBridge->Attributes = Bridge->Attributes; RootBridge->DmaAbove4G = Bridge->DmaAbove4G; + RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace; RootBridge->AllocationAttributes = Bridge->AllocationAttributes; RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath); RootBridge->DevicePathStr = DevicePathStr; @@ -168,17 +176,47 @@ CreateRootBridge ( CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE)); CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE)); CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE)); - + CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE)); for (Index = TypeIo; Index < TypeMax; Index++) { - RootBridge->ResAllocNode[Index].Type = Index; - RootBridge->ResAllocNode[Index].Base = 0; - RootBridge->ResAllocNode[Index].Length = 0; - RootBridge->ResAllocNode[Index].Status = ResNone; + switch (Index) { + case TypeBus: + Aperture = &RootBridge->Bus; + break; + case TypeIo: + Aperture = &RootBridge->Io; + break; + case TypeMem32: + Aperture = &RootBridge->Mem; + break; + case TypeMem64: + Aperture = &RootBridge->MemAbove4G; + break; + case TypePMem32: + Aperture = &RootBridge->PMem; + break; + case TypePMem64: + Aperture = &RootBridge->PMemAbove4G; + break; + default: + ASSERT (FALSE); + Aperture = NULL; + break; + } + RootBridge->ResAllocNode[Index].Type = Index; + if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) { + RootBridge->ResAllocNode[Index].Base = Aperture->Base; + RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1; + RootBridge->ResAllocNode[Index].Status = ResAllocated; + } else { + RootBridge->ResAllocNode[Index].Base = 0; + RootBridge->ResAllocNode[Index].Length = 0; + RootBridge->ResAllocNode[Index].Status = ResNone; + } } RootBridge->RootBridgeIo.SegmentNumber = Bridge->Segment; - RootBridge->RootBridgeIo.ParentHandle = HostBridgeHandle; RootBridge->RootBridgeIo.PollMem = RootBridgeIoPollMem; RootBridge->RootBridgeIo.PollIo = RootBridgeIoPollIo; RootBridge->RootBridgeIo.Mem.Read = RootBridgeIoMemRead; @@ -351,7 +389,7 @@ RootBridgeIoCheckParameter ( Address = PciRbAddr->Register; } Base = 0; - Limit = 0xFFF; + Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF; } if (Address < Base) { @@ -399,7 +437,6 @@ RootBridgeIoCheckParameter ( @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. **/ - EFI_STATUS EFIAPI RootBridgeIoPollMem ( @@ -987,7 +1024,6 @@ RootBridgeIoPciWrite ( } /** - Provides the PCI controller-specific address needed to access system memory for DMA. @@ -1007,7 +1043,6 @@ RootBridgeIoPciWrite ( @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. @retval EFI_DEVICE_ERROR The System hardware could not map the requested address. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources. - **/ EFI_STATUS EFIAPI @@ -1039,11 +1074,36 @@ RootBridgeIoMap ( RootBridge = ROOT_BRIDGE_FROM_THIS (This); + if (mIoMmuProtocol != NULL) { + if (!RootBridge->DmaAbove4G) { + // + // Clear 64bit support + // + if (Operation > EfiPciOperationBusMasterCommonBuffer) { + Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64); + } + } + Status = mIoMmuProtocol->Map ( + mIoMmuProtocol, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + return Status; + } + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; - if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) { + if ((!RootBridge->DmaAbove4G || + (Operation != EfiPciOperationBusMasterRead64 && + Operation != EfiPciOperationBusMasterWrite64 && + Operation != EfiPciOperationBusMasterCommonBuffer64)) && + ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) { + // - // If the root bridge can not handle performing DMA above 4GB but - // any part of the DMA transfer being mapped is above 4GB, then + // If the root bridge or the device cannot handle performing DMA above + // 4GB but any part of the DMA transfer being mapped is above 4GB, then // map the DMA transfer to a buffer below 4GB. // @@ -1156,8 +1216,18 @@ RootBridgeIoUnmap ( MAP_INFO *MapInfo; LIST_ENTRY *Link; PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + EFI_STATUS Status; + + if (mIoMmuProtocol != NULL) { + Status = mIoMmuProtocol->Unmap ( + mIoMmuProtocol, + Mapping + ); + return Status; + } RootBridge = ROOT_BRIDGE_FROM_THIS (This); + // // See if the Map() operation associated with this Unmap() required a mapping // buffer. If a mapping buffer was not required, then this function simply @@ -1274,8 +1344,27 @@ RootBridgeIoAllocateBuffer ( RootBridge = ROOT_BRIDGE_FROM_THIS (This); + if (mIoMmuProtocol != NULL) { + if (!RootBridge->DmaAbove4G) { + // + // Clear DUAL_ADDRESS_CYCLE + // + Attributes &= ~EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + } + Status = mIoMmuProtocol->AllocateBuffer ( + mIoMmuProtocol, + Type, + MemoryType, + Pages, + HostAddress, + Attributes + ); + return Status; + } + AllocateType = AllocateAnyPages; - if (!RootBridge->DmaAbove4G) { + if (!RootBridge->DmaAbove4G || + (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) { // // Limit allocations to memory below 4GB // @@ -1317,6 +1406,17 @@ RootBridgeIoFreeBuffer ( OUT VOID *HostAddress ) { + EFI_STATUS Status; + + if (mIoMmuProtocol != NULL) { + Status = mIoMmuProtocol->FreeBuffer ( + mIoMmuProtocol, + Pages, + HostAddress + ); + return Status; + } + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages); }