From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) by mx.groups.io with SMTP id smtpd.web08.11837.1630766529733325108 for ; Sat, 04 Sep 2021 07:42:09 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=i4L3yY96; spf=pass (domain: amazon.de, ip: 207.171.190.10, mailfrom: prvs=874eef02e=ncoleon@amazon.de) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1630766530; x=1662302530; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=KxHahaWbDZlz9oy436ZYugBcTZFWLwNDHB9UgXR2jeg=; b=i4L3yY96Gt7U6Hz21TnPPyOKmhD6oXU42oTox4LHBVuLGMNaNohqQbgX LsUZ9o43v3tcUSQqLveFqCh7ruGJsmCUV4sesQT3swzNbYrQoiY/cHETy AF0Um57hFiH+U4GcYGUFhRCN1fJWJhTNTJeKySCZharRbJrcQTIbjAUxA E=; X-IronPort-AV: E=Sophos;i="5.85,268,1624320000"; d="scan'208";a="145980319" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-1e-27fb8269.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-33001.sea14.amazon.com with ESMTP; 04 Sep 2021 14:42:02 +0000 Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-1e-27fb8269.us-east-1.amazon.com (Postfix) with ESMTPS id 7EF6BA1E17 for ; Sat, 4 Sep 2021 14:42:01 +0000 (UTC) Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.52) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.23; Sat, 4 Sep 2021 14:41:58 +0000 From: Nicolas Ojeda Leon To: CC: Nicolas Ojeda Leon , Alexander Graf Subject: [PATCH 2/5] OvmfPkg/PciHostBridgeUtilityLib: Initialize RootBridges apertures with spec Date: Sat, 4 Sep 2021 16:37:53 +0200 Message-ID: <60082b721c455f0762bdf4fd96c3544f7cdfb0c3.1630676569.git.ncoleon@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.52] X-ClientProxiedBy: EX13D16UWC001.ant.amazon.com (10.43.162.117) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Content-Type: text/plain Considering the "host-bridge-info" item from fw-cfg, the apertures for all root bridges are initialized and used in the creation of the root bridge objects that determine the resources each host bridge can use. PCI MMIO apertures are merged to produce a single low memory and a single high memory apertures matching current Ovmf allocation strategy which includes the EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM attribute. Prefetchable and non-prefetchable ranges are merged together to produce a single aperture covering both ranges. Therefore, if both prefetchable and non-prefetchable apertures are defined for one of the address spaces (32-bit or 64-bit), these 2 must be contiguous. For platforms having multiple PCI host bridges, hypervisor builds and propagates the resource specification (MMIO apertures) for each of the host bridges over fw-cfg. These specifications determine the usable windows in low and high memory, overwriting any calculated range and providing both control for the hypervisor to configure the apertures as well as possibility to use multiple host bridges. Signed-off-by: Nicolas Ojeda Leon Cc: Alexander Graf --- .../PciHostBridgeUtilityLib.c | 128 +++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c index d2296f3308..7567da8423 100644 --- a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c +++ b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -186,6 +187,66 @@ PciHostBridgeUtilityUninitRootBridge ( FreePool (RootBus->DevicePath); } +/** + Interpret the MMIO resources in HostBridge and set the apertures + in 32-bit space (Mem) and 64-bit space (MemABove4G) accordingly. + + The 2 types of apertures in each space (prefetchable and + non-prefetchable) are merged into a single window, hence if both + types of apertures are defined for a root bridges, these must be + contiguous. + + @param[in] HostBridge Root bridge's resources specification + + @param[out] Mem 32-bit MMIO aperture + + @param[out] MemAbove4G 64-bit MMIO aperture +**/ +STATIC +VOID +InitRootBridgeApertures ( + IN HOST_BRIDGE_INFO *HostBridge, + OUT PCI_ROOT_BRIDGE_APERTURE *Mem, + OUT PCI_ROOT_BRIDGE_APERTURE *MemAbove4G + + ) +{ + if (HostBridge == NULL || Mem == NULL || MemAbove4G == NULL) { + return; + } + + MemAbove4G->Base = MAX_UINT64; + MemAbove4G->Limit = 0; + + if (HostBridge->highmem_start != MAX_UINT64 && + HostBridge->highmem_end != MAX_UINT64) { + MemAbove4G->Base = HostBridge->highmem_start; + MemAbove4G->Limit = HostBridge->highmem_end; + } + + if (HostBridge->highmem_pref_start != MAX_UINT64 && + HostBridge->highmem_pref_end != MAX_UINT64) { + if (HostBridge->highmem_pref_start < MemAbove4G->Base) + MemAbove4G->Base = HostBridge->highmem_pref_start; + + if (HostBridge->highmem_pref_end > MemAbove4G->Limit) + MemAbove4G->Limit = HostBridge->highmem_pref_end; + } + + // + // Check if prefetchable range is valid and merge both ranges into a single + // 32-bit aperture. + // In case both prefetchable and non-prefetchable ranges are defined, + // these must be contiguous. + // + Mem->Base = HostBridge->lowmem_start; + if (HostBridge->lowmem_pref_end != MAX_UINT32) { + Mem->Limit = HostBridge->lowmem_pref_end; + } else { + Mem->Limit = HostBridge->lowmem_end; + } +} + /** Utility function to return all the root bridge instances in an array. @@ -241,6 +302,7 @@ PciHostBridgeUtilityGetRootBridges ( UINTN Initialized; UINTN LastRootBridgeNumber; UINTN RootBridgeNumber; + HOST_BRIDGE_INFO *RootBridgesInfo; *Count = 0; @@ -277,13 +339,54 @@ PciHostBridgeUtilityGetRootBridges ( __FUNCTION__, ExtraRootBridges)); } + // + // Initialize RootBridgeInfo pointer, so in case no fw-cfg item is found + // the default configuration is used. + // + RootBridgesInfo = NULL; + Initialized = 0; + Bridges = NULL; + + // + // Hypervisor can provide, over fw-cfg, resource specifications for one or + // more PCI host bridges. + // + Status = QemuFwCfgFindFile ("etc/host-bridge-info", &FwCfgItem, &FwCfgSize); + + if (!EFI_ERROR (Status)) { + UINTN RootBridgesInfoSize = (1 + (UINTN)ExtraRootBridges) * + sizeof(HOST_BRIDGE_INFO); + RootBridgesInfo = AllocatePool (RootBridgesInfoSize); + + if (RootBridgesInfo == NULL) { + DEBUG ((DEBUG_ERROR, + "%a: Failed to allocate memory for resources info\n", __FUNCTION__)); + return NULL; + } + + // + // Read the resource information of all Root Bridges from fw-cfg + // + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, RootBridgesInfo); + + if (FwCfgSize != RootBridgesInfoSize) { + DEBUG ((DEBUG_ERROR, + "%a: Invalid HostBridgeInfo fw-cfg item size. Expected %ld, got %ld\n", + __FUNCTION__, RootBridgesInfoSize, FwCfgSize)); + goto FreeBridges; + } + DEBUG ((DEBUG_INFO, "%a: Resources for %Lu root buses found in fw-cfg\n", + __FUNCTION__, ExtraRootBridges + 1)); + } + // // Allocate the "main" root bridge, and any extra root bridges. // Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges); if (Bridges == NULL) { DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); - return NULL; + goto FreeBridges; } Initialized = 0; @@ -309,6 +412,11 @@ PciHostBridgeUtilityGetRootBridges ( } } if (Device <= PCI_MAX_DEVICE) { + // + // If resources obtained from fw-cfg, use those values + // + InitRootBridgeApertures(&RootBridgesInfo[Initialized], Mem, MemAbove4G); + // // Found the next root bus. We can now install the *previous* one, // because now we know how big a bus number range *that* one has, for any @@ -341,6 +449,8 @@ PciHostBridgeUtilityGetRootBridges ( // Install the last root bus (which might be the only, ie. main, root bus, if // we've found no extra root buses). // + InitRootBridgeApertures(&RootBridgesInfo[Initialized], Mem, MemAbove4G); + Status = PciHostBridgeUtilityInitRootBridge ( Attributes, Attributes, @@ -362,6 +472,14 @@ PciHostBridgeUtilityGetRootBridges ( ++Initialized; *Count = Initialized; + + // + // If resources were allocated for host bridges info, release them + // + if (RootBridgesInfo) { + FreePool(RootBridgesInfo); + } + return Bridges; FreeBridges: @@ -370,7 +488,13 @@ FreeBridges: PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]); } - FreePool (Bridges); + if (Bridges) { + FreePool (Bridges); + } + + if (RootBridgesInfo) { + FreePool(RootBridgesInfo); + } return NULL; } -- 2.17.1 Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879