From patchwork Mon Jan 15 14:46:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gary guo X-Patchwork-Id: 124532 Delivered-To: patch@linaro.org Received: by 10.46.64.148 with SMTP id r20csp692438lje; Mon, 15 Jan 2018 06:46:58 -0800 (PST) X-Google-Smtp-Source: ACJfBosgmRoAyxFYvoWG+lZOUm5Tauu8Awy40U+Ht+IuBfRr98mbp1F+AdeT2fV6lfj9o4MnIxqX X-Received: by 10.101.100.204 with SMTP id t12mr27678409pgv.135.1516027618393; Mon, 15 Jan 2018 06:46:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516027618; cv=none; d=google.com; s=arc-20160816; b=eraw6Uy+gbkCLd4tMdKvGOW98pWryVQYOvMcO2t7VZFcDfFAyDsRR2Xc9B5NGUaUBY nZ3Mabs/N4L3MSs4eZcgb3SdwdiPJQoIVNNXiUoWBY7ZWDqV4htY/gx4eGKD1CWKXTGv QX5ZxtaBPierCHhcyaIAIeF2QJJBZOcz25SHhvsgeYG7ntdzXqVgatfElMpdJ+Mi/Cjf zMgiORrNgmef/ow9LakrCnqpJVQOEg92ggCjg4f9M/uqYs1XNZDai94+lLrXA4xlkYjX PPpBS5Jc5nX/hvPNLnid2zsesZ/TX/2xSXVamA5K2+msoRotLSHiUt97wREvwekTMY65 SinQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=ljTVpojYac5JclS6nGhSmS/1lEI2+QBFUc+Zxbb3c5w=; b=frgpNnwl39NA/yYM1uA+QvjabQsabNxwSyhXAXM9p6S+9A9Z6PAYja/I8uCLR499dY kgqYGHqegYtS3iUNaP/aFUhBxsD4gAbctVsLgslv/juab7bPF+BoG/nbfg8YFqWXAMCi R0p/oHgh+zb0GvJ/TVxbxpO1s/bW3G8+Kt5GpvtOtC3EUZTf3U5iybl8JiBzpu7lP496 1CkV5N2tYguT6EONMRWiAAHZWELu+vM7B2Cbftt2oMjkjws97aCMUM1jqpe9mEW4PkXT uzHXQgrgpAosy/GXClRgXGaShAwjlB6pcMctba7KWfT/QX27c3sKNqng5aKQz2ZL7YhD cI/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FxFmChQt; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from ml01.01.org (ml01.01.org. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id h192si2575104pgc.123.2018.01.15.06.46.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 15 Jan 2018 06:46:58 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FxFmChQt; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 957812094561A; Mon, 15 Jan 2018 06:41:38 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c01::244; helo=mail-pl0-x244.google.com; envelope-from=heyi.guo@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-pl0-x244.google.com (mail-pl0-x244.google.com [IPv6:2607:f8b0:400e:c01::244]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id BD29C222DDBF2 for ; Mon, 15 Jan 2018 06:41:36 -0800 (PST) Received: by mail-pl0-x244.google.com with SMTP id 66so3878973plc.13 for ; Mon, 15 Jan 2018 06:46:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=idAkWO7mHWOmHWXXyVjPV5GVOReD6Yc7gMWjsDGFXHY=; b=FxFmChQt+D61aw7XO1dr51pO6RbJ306zXuEe3u7L3kEGhrXEo7mRY0a7PT81jntSrz mBwrx8/uAzrSoWOdPRfH1srzlRt35qsCnerL9cjrZxgWGWR543gsjLnvcFtrXcYDeqGX P81d+VMwfVS2cNCLeXb+alG6WnwKTmg4GY1fU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=idAkWO7mHWOmHWXXyVjPV5GVOReD6Yc7gMWjsDGFXHY=; b=H9scNdNTfOo4nIGm8DuvYoNvaUKt6N39dnSm/eVlMWdgdn7tzrdZQVPwzqM0yBfrQd GjD15x7HcH5UiC+Q/An7nbjk2ZZwSaElz/Ur/+Gr38wB/r1mhhN9Q9vkSMCJhtJ124Tn fJzhzfsxaHGCG2CyZFHvh+V6BUmqDTYHfH5MJey2mLQgTdgW8kJ+WYxiff8fOMVEDnBG d2r6oikSQGzPhEq6yU4or7g6OPiNEAiiRyKj7YinP9OTEDTj1niidEmGKyzIY8PRFGio fe7v70xJlkXrtrI/kLhbhWr6oWZ76ip1nZVkYDC/cv2X2rANZfe3fHT2VcDfi2elkL0P WGDw== X-Gm-Message-State: AKwxytdtTLDvNNGTrG4MAwkeZ30tn3xcI99sH3Okzcvq47lkBJZlyZzN ZKA/e7CnCWSXNe12KG6P9IYaEg== X-Received: by 10.159.218.4 with SMTP id v4mr11798747plp.252.1516027614229; Mon, 15 Jan 2018 06:46:54 -0800 (PST) Received: from localhost.localdomain ([119.145.15.121]) by smtp.gmail.com with ESMTPSA id f78sm15989889pfk.144.2018.01.15.06.46.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 15 Jan 2018 06:46:53 -0800 (PST) From: Heyi Guo To: linaro-uefi@lists.linaro.org, edk2-devel@lists.01.org Date: Mon, 15 Jan 2018 22:46:40 +0800 Message-Id: <1516027600-32172-1-git-send-email-heyi.guo@linaro.org> X-Mailer: git-send-email 2.7.4 Subject: [edk2] [RFC] MdeModulePkg/PciHostBridgeDxe: Add support for address translation X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ruiyu Ni , Heyi Guo , Eric Dong , Star Zeng , Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" This is the draft patch for the discussion posted in edk2-devel mailing list: https://lists.01.org/pipermail/edk2-devel/2017-December/019289.html As discussed in the mailing list, we'd like to add support for PCI address translation which is necessary for some non-x86 platforms. I also want to minimize the changes to the generic host bridge driver and platform PciHostBridgeLib implemetations, so additional two interfaces are added to expose translation information of the platform. To be generic, I add translation for each type of IO or memory resources. The patch is still a RFC, so I only passed the build for qemu64 and the function has not been tested yet. Please let me know your comments about it. Thanks. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Heyi Guo Cc: Ruiyu Ni Cc: Ard Biesheuvel Cc: Star Zeng Cc: Eric Dong --- .../FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 19 ++++ .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 53 ++++++++--- .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 8 +- .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 101 ++++++++++++++++++--- MdeModulePkg/Include/Library/PciHostBridgeLib.h | 36 ++++++++ 5 files changed, 192 insertions(+), 25 deletions(-) -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c index 5b9c887..0c8371a 100644 --- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c @@ -360,6 +360,16 @@ PciHostBridgeGetRootBridges ( return &mRootBridge; } +PCI_ROOT_BRIDGE_TRANSLATION * +EFIAPI +PciHostBridgeGetTranslations ( + UINTN *Count + ) +{ + *Count = 0; + return NULL; +} + /** Free the root bridge instances array returned from PciHostBridgeGetRootBridges(). @@ -377,6 +387,15 @@ PciHostBridgeFreeRootBridges ( ASSERT (Count == 1); } +VOID +EFIAPI +PciHostBridgeFreeTranslations ( + PCI_ROOT_BRIDGE_TRANSLATION *Translations, + UINTN Count + ) +{ +} + /** Inform the platform that the resource conflict happens. diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c index 1494848..835e411 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c @@ -360,18 +360,38 @@ InitializePciHostBridge ( PCI_HOST_BRIDGE_INSTANCE *HostBridge; PCI_ROOT_BRIDGE_INSTANCE *RootBridge; PCI_ROOT_BRIDGE *RootBridges; + PCI_ROOT_BRIDGE_TRANSLATION *Translations; UINTN RootBridgeCount; + UINTN TranslationCount; UINTN Index; PCI_ROOT_BRIDGE_APERTURE *MemApertures[4]; + UINT64 MemTranslation[4]; UINTN MemApertureIndex; BOOLEAN ResourceAssigned; LIST_ENTRY *Link; + UINT64 Trans; RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount); if ((RootBridges == NULL) || (RootBridgeCount == 0)) { return EFI_UNSUPPORTED; } + Translations = PciHostBridgeGetTranslations (&TranslationCount); + if (Translations == NULL || TranslationCount == 0) { + TranslationCount = 0; + Translations = AllocateZeroPool (RootBridgeCount * sizeof (*Translations)); + if (Translations == NULL) { + PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount); + return EFI_OUT_OF_RESOURCES; + } + } + + if (TranslationCount != 0 && TranslationCount != RootBridgeCount) { + DEBUG ((DEBUG_ERROR, "Error: count of root bridges (%d) and translation (%d) are different!\n", + RootBridgeCount, TranslationCount)); + return EFI_INVALID_PARAMETER; + } + Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo); @@ -395,7 +415,7 @@ InitializePciHostBridge ( // // Create Root Bridge Handle Instance // - RootBridge = CreateRootBridge (&RootBridges[Index]); + RootBridge = CreateRootBridge (&RootBridges[Index], &Translations[Index]); ASSERT (RootBridge != NULL); if (RootBridge == NULL) { continue; @@ -411,8 +431,9 @@ InitializePciHostBridge ( } if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) { + Trans = Translations[Index].IoTranslation; Status = AddIoSpace ( - RootBridges[Index].Io.Base, + RootBridges[Index].Io.Base + Trans, RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1 ); ASSERT_EFI_ERROR (Status); @@ -422,7 +443,7 @@ InitializePciHostBridge ( EfiGcdIoTypeIo, 0, RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1, - &RootBridges[Index].Io.Base, + &RootBridges[Index].Io.Base + Trans, gImageHandle, NULL ); @@ -437,20 +458,24 @@ InitializePciHostBridge ( // the MEM aperture in Mem // MemApertures[0] = &RootBridges[Index].Mem; + MemTranslation[0] = Translations[Index].MemTranslation; MemApertures[1] = &RootBridges[Index].MemAbove4G; + MemTranslation[1] = Translations[Index].MemAbove4GTranslation; MemApertures[2] = &RootBridges[Index].PMem; + MemTranslation[2] = Translations[Index].PMemTranslation; MemApertures[3] = &RootBridges[Index].PMemAbove4G; + MemTranslation[3] = Translations[Index].PMemAbove4GTranslation; for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) { if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) { Status = AddMemoryMappedIoSpace ( - MemApertures[MemApertureIndex]->Base, + MemApertures[MemApertureIndex]->Base + MemTranslation[MemApertureIndex], MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1, EFI_MEMORY_UC ); ASSERT_EFI_ERROR (Status); Status = gDS->SetMemorySpaceAttributes ( - MemApertures[MemApertureIndex]->Base, + MemApertures[MemApertureIndex]->Base + MemTranslation[MemApertureIndex], MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1, EFI_MEMORY_UC ); @@ -463,7 +488,7 @@ InitializePciHostBridge ( EfiGcdMemoryTypeMemoryMappedIo, 0, MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1, - &MemApertures[MemApertureIndex]->Base, + &MemApertures[MemApertureIndex]->Base + MemTranslation[MemApertureIndex], gImageHandle, NULL ); @@ -514,7 +539,13 @@ InitializePciHostBridge ( ); ASSERT_EFI_ERROR (Status); } + PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount); + if (TranslationCount == 0) { + FreePool (Translations); + } else { + PciHostBridgeFreeTranslations (Translations, TranslationCount); + } if (!EFI_ERROR (Status)) { mIoMmuEvent = EfiCreateProtocolNotifyEvent ( @@ -828,7 +859,7 @@ NotifyPhase ( FALSE, RootBridge->ResAllocNode[Index].Length, MIN (15, BitsOfAlignment), - ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1), + ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1) + RootBridge->IoTranslation, RootBridge->Io.Limit ); break; @@ -838,7 +869,7 @@ NotifyPhase ( TRUE, RootBridge->ResAllocNode[Index].Length, MIN (63, BitsOfAlignment), - ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1), + ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1) + RootBridge->MemAbove4GTranslation, RootBridge->MemAbove4G.Limit ); if (BaseAddress != MAX_UINT64) { @@ -853,7 +884,7 @@ NotifyPhase ( TRUE, RootBridge->ResAllocNode[Index].Length, MIN (31, BitsOfAlignment), - ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1), + ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1) + RootBridge->MemTranslation, RootBridge->Mem.Limit ); break; @@ -863,7 +894,7 @@ NotifyPhase ( TRUE, RootBridge->ResAllocNode[Index].Length, MIN (63, BitsOfAlignment), - ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1), + ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1) + RootBridge->PMemAbove4GTranslation, RootBridge->PMemAbove4G.Limit ); if (BaseAddress != MAX_UINT64) { @@ -877,7 +908,7 @@ NotifyPhase ( TRUE, RootBridge->ResAllocNode[Index].Length, MIN (31, BitsOfAlignment), - ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1), + ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1) + RootBridge->PMemTranslation, RootBridge->PMem.Limit ); break; diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h index d3dfb57..449c4b3 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h @@ -73,6 +73,11 @@ typedef struct { PCI_ROOT_BRIDGE_APERTURE PMem; PCI_ROOT_BRIDGE_APERTURE MemAbove4G; PCI_ROOT_BRIDGE_APERTURE PMemAbove4G; + UINT64 IoTranslation; + UINT64 MemTranslation; + UINT64 MemAbove4GTranslation; + UINT64 PMemTranslation; + UINT64 PMemAbove4GTranslation; BOOLEAN DmaAbove4G; BOOLEAN NoExtendedConfigSpace; VOID *ConfigBuffer; @@ -98,7 +103,8 @@ typedef struct { **/ PCI_ROOT_BRIDGE_INSTANCE * CreateRootBridge ( - IN PCI_ROOT_BRIDGE *Bridge + IN PCI_ROOT_BRIDGE *Bridge, + IN PCI_ROOT_BRIDGE_TRANSLATION *Translation ); // diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c index dc06c16..84b2d5a 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c @@ -67,7 +67,8 @@ UINT8 mOutStride[] = { **/ PCI_ROOT_BRIDGE_INSTANCE * CreateRootBridge ( - IN PCI_ROOT_BRIDGE *Bridge + IN PCI_ROOT_BRIDGE *Bridge, + IN PCI_ROOT_BRIDGE_TRANSLATION *Translation ) { PCI_ROOT_BRIDGE_INSTANCE *RootBridge; @@ -87,11 +88,21 @@ CreateRootBridge ( (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 ((DEBUG_INFO, " Io: %lx - %lx translation=%lx\n", + Bridge->Io.Base, Bridge->Io.Limit, Translation->IoTranslation + )); + DEBUG ((DEBUG_INFO, " Mem: %lx - %lx translation=%lx\n", + Bridge->Mem.Base, Bridge->Mem.Limit, Translation->MemTranslation + )); + DEBUG ((DEBUG_INFO, " MemAbove4G: %lx - %lx translation=%lx\n", + Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit, Translation->MemAbove4GTranslation + )); + DEBUG ((DEBUG_INFO, " PMem: %lx - %lx translation=%lx\n", + Bridge->PMem.Base, Bridge->PMem.Limit, Translation->PMemTranslation + )); + DEBUG ((DEBUG_INFO, " PMemAbove4G: %lx - %lx translation=%lx\n", + Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit, Translation->PMemAbove4GTranslation + )); // // Make sure Mem and MemAbove4G apertures are valid @@ -174,10 +185,15 @@ CreateRootBridge ( CopyMem (&RootBridge->Bus, &Bridge->Bus, sizeof (PCI_ROOT_BRIDGE_APERTURE)); CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + RootBridge->IoTranslation = Translation->IoTranslation; CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + RootBridge->MemTranslation = Translation->MemTranslation; CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + RootBridge->MemAbove4GTranslation = Translation->MemAbove4GTranslation; CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + RootBridge->PMemTranslation = Translation->PMemTranslation; CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE)); + RootBridge->PMemAbove4GTranslation = Translation->PMemAbove4GTranslation; for (Index = TypeIo; Index < TypeMax; Index++) { switch (Index) { @@ -403,6 +419,28 @@ RootBridgeIoCheckParameter ( return EFI_SUCCESS; } +EFI_STATUS +RootBridgeIoGetMemTranslation ( + IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge, + IN UINT64 Address, + IN OUT UINT64 *Translation + ) +{ + if (Address >= RootBridge->Mem.Base && Address <= RootBridge->Mem.Limit) { + *Translation = RootBridge->MemTranslation; + } else if (Address >= RootBridge->PMem.Base && Address <= RootBridge->PMem.Limit) { + *Translation = RootBridge->PMemTranslation; + } else if (Address >= RootBridge->MemAbove4G.Base && Address <= RootBridge->MemAbove4G.Limit) { + *Translation = RootBridge->MemAbove4GTranslation; + } else if (Address >= RootBridge->PMemAbove4G.Base && Address <= RootBridge->PMemAbove4G.Limit) { + *Translation = RootBridge->PMemAbove4GTranslation; + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + /** Polls an address in memory mapped I/O space until an exit condition is met, or a timeout occurs. @@ -658,13 +696,22 @@ RootBridgeIoMemRead ( ) { EFI_STATUS Status; + PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + UINT64 Translation; Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } - return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer); + + RootBridge = ROOT_BRIDGE_FROM_THIS (This); + Status = RootBridgeIoGetMemTranslation (RootBridge, Address, &Translation); + if (EFI_ERROR (Status)) { + return Status; + } + + return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer); } /** @@ -705,13 +752,22 @@ RootBridgeIoMemWrite ( ) { EFI_STATUS Status; + PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + UINT64 Translation; Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } - return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer); + + RootBridge = ROOT_BRIDGE_FROM_THIS (This); + Status = RootBridgeIoGetMemTranslation (RootBridge, Address, &Translation); + if (EFI_ERROR (Status)) { + return Status; + } + + return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + Translation, Count, Buffer); } /** @@ -746,6 +802,8 @@ RootBridgeIoIoRead ( ) { EFI_STATUS Status; + PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + Status = RootBridgeIoCheckParameter ( This, IoOperation, Width, Address, Count, Buffer @@ -753,7 +811,10 @@ RootBridgeIoIoRead ( if (EFI_ERROR (Status)) { return Status; } - return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer); + + RootBridge = ROOT_BRIDGE_FROM_THIS (This); + + return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->IoTranslation, Count, Buffer); } /** @@ -788,6 +849,8 @@ RootBridgeIoIoWrite ( ) { EFI_STATUS Status; + PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + Status = RootBridgeIoCheckParameter ( This, IoOperation, Width, Address, Count, Buffer @@ -795,7 +858,10 @@ RootBridgeIoIoWrite ( if (EFI_ERROR (Status)) { return Status; } - return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer); + + RootBridge = ROOT_BRIDGE_FROM_THIS (This); + + return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address + RootBridge->IoTranslation, Count, Buffer); } /** @@ -1621,19 +1687,28 @@ RootBridgeIoConfiguration ( switch (ResAllocNode->Type) { case TypeIo: - Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + Descriptor->AddrTranslationOffset = RootBridge->IoTranslation; break; case TypePMem32: - Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE; + Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE; + Descriptor->AddrTranslationOffset = RootBridge->PMemTranslation; + Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Descriptor->AddrSpaceGranularity = 32; case TypeMem32: + Descriptor->AddrTranslationOffset = RootBridge->MemTranslation; Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Descriptor->AddrSpaceGranularity = 32; break; case TypePMem64: - Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE; + Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE; + Descriptor->AddrTranslationOffset = RootBridge->PMemAbove4GTranslation; + Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Descriptor->AddrSpaceGranularity = 64; case TypeMem64: + Descriptor->AddrTranslationOffset = RootBridge->MemAbove4GTranslation; Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Descriptor->AddrSpaceGranularity = 64; break; diff --git a/MdeModulePkg/Include/Library/PciHostBridgeLib.h b/MdeModulePkg/Include/Library/PciHostBridgeLib.h index d42e9ec..4c297fd 100644 --- a/MdeModulePkg/Include/Library/PciHostBridgeLib.h +++ b/MdeModulePkg/Include/Library/PciHostBridgeLib.h @@ -53,6 +53,14 @@ typedef struct { EFI_DEVICE_PATH_PROTOCOL *DevicePath; ///< Device path. } PCI_ROOT_BRIDGE; +typedef struct { + UINT64 IoTranslation; + UINT64 MemTranslation; + UINT64 MemAbove4GTranslation; + UINT64 PMemTranslation; + UINT64 PMemAbove4GTranslation; +} PCI_ROOT_BRIDGE_TRANSLATION; + /** Return all the root bridge instances in an array. @@ -69,6 +77,21 @@ PciHostBridgeGetRootBridges ( ); /** + Return all the root bridge instances in an array. + + @param Count Return the count of root bridge instances. + + @return All the root bridge instances in an array. + The array should be passed into PciHostBridgeFreeRootBridges() + when it's not used. +**/ +PCI_ROOT_BRIDGE_TRANSLATION * +EFIAPI +PciHostBridgeGetTranslations ( + UINTN *Count + ); + +/** Free the root bridge instances array returned from PciHostBridgeGetRootBridges(). @param Bridges The root bridge instances array. @@ -82,6 +105,19 @@ PciHostBridgeFreeRootBridges ( ); /** + Free the root bridge instances array returned from PciHostBridgeGetRootBridges(). + + @param Bridges The root bridge instances array. + @param Count The count of the array. +**/ +VOID +EFIAPI +PciHostBridgeFreeTranslations ( + PCI_ROOT_BRIDGE_TRANSLATION *Bridges, + UINTN Count + ); + +/** Inform the platform that the resource conflict happens. @param HostBridgeHandle Handle of the Host Bridge.