18c2ecf20Sopenharmony_ci=================================================== 28c2ecf20Sopenharmony_ciPCI Express I/O Virtualization Resource on Powerenv 38c2ecf20Sopenharmony_ci=================================================== 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciWei Yang <weiyang@linux.vnet.ibm.com> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciBenjamin Herrenschmidt <benh@au1.ibm.com> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciBjorn Helgaas <bhelgaas@google.com> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci26 Aug 2014 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciThis document describes the requirement from hardware for PCI MMIO resource 148c2ecf20Sopenharmony_cisizing and assignment on PowerKVM and how generic PCI code handles this 158c2ecf20Sopenharmony_cirequirement. The first two sections describe the concepts of Partitionable 168c2ecf20Sopenharmony_ciEndpoints and the implementation on P8 (IODA2). The next two sections talks 178c2ecf20Sopenharmony_ciabout considerations on enabling SRIOV on IODA2. 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci1. Introduction to Partitionable Endpoints 208c2ecf20Sopenharmony_ci========================================== 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciA Partitionable Endpoint (PE) is a way to group the various resources 238c2ecf20Sopenharmony_ciassociated with a device or a set of devices to provide isolation between 248c2ecf20Sopenharmony_cipartitions (i.e., filtering of DMA, MSIs etc.) and to provide a mechanism 258c2ecf20Sopenharmony_cito freeze a device that is causing errors in order to limit the possibility 268c2ecf20Sopenharmony_ciof propagation of bad data. 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciThere is thus, in HW, a table of PE states that contains a pair of "frozen" 298c2ecf20Sopenharmony_cistate bits (one for MMIO and one for DMA, they get set together but can be 308c2ecf20Sopenharmony_cicleared independently) for each PE. 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciWhen a PE is frozen, all stores in any direction are dropped and all loads 338c2ecf20Sopenharmony_cireturn all 1's value. MSIs are also blocked. There's a bit more state that 348c2ecf20Sopenharmony_cicaptures things like the details of the error that caused the freeze etc., but 358c2ecf20Sopenharmony_cithat's not critical. 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciThe interesting part is how the various PCIe transactions (MMIO, DMA, ...) 388c2ecf20Sopenharmony_ciare matched to their corresponding PEs. 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciThe following section provides a rough description of what we have on P8 418c2ecf20Sopenharmony_ci(IODA2). Keep in mind that this is all per PHB (PCI host bridge). Each PHB 428c2ecf20Sopenharmony_ciis a completely separate HW entity that replicates the entire logic, so has 438c2ecf20Sopenharmony_ciits own set of PEs, etc. 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci2. Implementation of Partitionable Endpoints on P8 (IODA2) 468c2ecf20Sopenharmony_ci========================================================== 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciP8 supports up to 256 Partitionable Endpoints per PHB. 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci * Inbound 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci For DMA, MSIs and inbound PCIe error messages, we have a table (in 538c2ecf20Sopenharmony_ci memory but accessed in HW by the chip) that provides a direct 548c2ecf20Sopenharmony_ci correspondence between a PCIe RID (bus/dev/fn) with a PE number. 558c2ecf20Sopenharmony_ci We call this the RTT. 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci - For DMA we then provide an entire address space for each PE that can 588c2ecf20Sopenharmony_ci contain two "windows", depending on the value of PCI address bit 59. 598c2ecf20Sopenharmony_ci Each window can be configured to be remapped via a "TCE table" (IOMMU 608c2ecf20Sopenharmony_ci translation table), which has various configurable characteristics 618c2ecf20Sopenharmony_ci not described here. 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci - For MSIs, we have two windows in the address space (one at the top of 648c2ecf20Sopenharmony_ci the 32-bit space and one much higher) which, via a combination of the 658c2ecf20Sopenharmony_ci address and MSI value, will result in one of the 2048 interrupts per 668c2ecf20Sopenharmony_ci bridge being triggered. There's a PE# in the interrupt controller 678c2ecf20Sopenharmony_ci descriptor table as well which is compared with the PE# obtained from 688c2ecf20Sopenharmony_ci the RTT to "authorize" the device to emit that specific interrupt. 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci - Error messages just use the RTT. 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci * Outbound. That's where the tricky part is. 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci Like other PCI host bridges, the Power8 IODA2 PHB supports "windows" 758c2ecf20Sopenharmony_ci from the CPU address space to the PCI address space. There is one M32 768c2ecf20Sopenharmony_ci window and sixteen M64 windows. They have different characteristics. 778c2ecf20Sopenharmony_ci First what they have in common: they forward a configurable portion of 788c2ecf20Sopenharmony_ci the CPU address space to the PCIe bus and must be naturally aligned 798c2ecf20Sopenharmony_ci power of two in size. The rest is different: 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci - The M32 window: 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci * Is limited to 4GB in size. 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci * Drops the top bits of the address (above the size) and replaces 868c2ecf20Sopenharmony_ci them with a configurable value. This is typically used to generate 878c2ecf20Sopenharmony_ci 32-bit PCIe accesses. We configure that window at boot from FW and 888c2ecf20Sopenharmony_ci don't touch it from Linux; it's usually set to forward a 2GB 898c2ecf20Sopenharmony_ci portion of address space from the CPU to PCIe 908c2ecf20Sopenharmony_ci 0x8000_0000..0xffff_ffff. (Note: The top 64KB are actually 918c2ecf20Sopenharmony_ci reserved for MSIs but this is not a problem at this point; we just 928c2ecf20Sopenharmony_ci need to ensure Linux doesn't assign anything there, the M32 logic 938c2ecf20Sopenharmony_ci ignores that however and will forward in that space if we try). 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci * It is divided into 256 segments of equal size. A table in the chip 968c2ecf20Sopenharmony_ci maps each segment to a PE#. That allows portions of the MMIO space 978c2ecf20Sopenharmony_ci to be assigned to PEs on a segment granularity. For a 2GB window, 988c2ecf20Sopenharmony_ci the segment granularity is 2GB/256 = 8MB. 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci Now, this is the "main" window we use in Linux today (excluding 1018c2ecf20Sopenharmony_ci SR-IOV). We basically use the trick of forcing the bridge MMIO windows 1028c2ecf20Sopenharmony_ci onto a segment alignment/granularity so that the space behind a bridge 1038c2ecf20Sopenharmony_ci can be assigned to a PE. 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci Ideally we would like to be able to have individual functions in PEs 1068c2ecf20Sopenharmony_ci but that would mean using a completely different address allocation 1078c2ecf20Sopenharmony_ci scheme where individual function BARs can be "grouped" to fit in one or 1088c2ecf20Sopenharmony_ci more segments. 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci - The M64 windows: 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci * Must be at least 256MB in size. 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci * Do not translate addresses (the address on PCIe is the same as the 1158c2ecf20Sopenharmony_ci address on the PowerBus). There is a way to also set the top 14 1168c2ecf20Sopenharmony_ci bits which are not conveyed by PowerBus but we don't use this. 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci * Can be configured to be segmented. When not segmented, we can 1198c2ecf20Sopenharmony_ci specify the PE# for the entire window. When segmented, a window 1208c2ecf20Sopenharmony_ci has 256 segments; however, there is no table for mapping a segment 1218c2ecf20Sopenharmony_ci to a PE#. The segment number *is* the PE#. 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci * Support overlaps. If an address is covered by multiple windows, 1248c2ecf20Sopenharmony_ci there's a defined ordering for which window applies. 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci We have code (fairly new compared to the M32 stuff) that exploits that 1278c2ecf20Sopenharmony_ci for large BARs in 64-bit space: 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci We configure an M64 window to cover the entire region of address space 1308c2ecf20Sopenharmony_ci that has been assigned by FW for the PHB (about 64GB, ignore the space 1318c2ecf20Sopenharmony_ci for the M32, it comes out of a different "reserve"). We configure it 1328c2ecf20Sopenharmony_ci as segmented. 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci Then we do the same thing as with M32, using the bridge alignment 1358c2ecf20Sopenharmony_ci trick, to match to those giant segments. 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci Since we cannot remap, we have two additional constraints: 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci - We do the PE# allocation *after* the 64-bit space has been assigned 1408c2ecf20Sopenharmony_ci because the addresses we use directly determine the PE#. We then 1418c2ecf20Sopenharmony_ci update the M32 PE# for the devices that use both 32-bit and 64-bit 1428c2ecf20Sopenharmony_ci spaces or assign the remaining PE# to 32-bit only devices. 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci - We cannot "group" segments in HW, so if a device ends up using more 1458c2ecf20Sopenharmony_ci than one segment, we end up with more than one PE#. There is a HW 1468c2ecf20Sopenharmony_ci mechanism to make the freeze state cascade to "companion" PEs but 1478c2ecf20Sopenharmony_ci that only works for PCIe error messages (typically used so that if 1488c2ecf20Sopenharmony_ci you freeze a switch, it freezes all its children). So we do it in 1498c2ecf20Sopenharmony_ci SW. We lose a bit of effectiveness of EEH in that case, but that's 1508c2ecf20Sopenharmony_ci the best we found. So when any of the PEs freezes, we freeze the 1518c2ecf20Sopenharmony_ci other ones for that "domain". We thus introduce the concept of 1528c2ecf20Sopenharmony_ci "master PE" which is the one used for DMA, MSIs, etc., and "secondary 1538c2ecf20Sopenharmony_ci PEs" that are used for the remaining M64 segments. 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci We would like to investigate using additional M64 windows in "single 1568c2ecf20Sopenharmony_ci PE" mode to overlay over specific BARs to work around some of that, for 1578c2ecf20Sopenharmony_ci example for devices with very large BARs, e.g., GPUs. It would make 1588c2ecf20Sopenharmony_ci sense, but we haven't done it yet. 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci3. Considerations for SR-IOV on PowerKVM 1618c2ecf20Sopenharmony_ci======================================== 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci * SR-IOV Background 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci The PCIe SR-IOV feature allows a single Physical Function (PF) to 1668c2ecf20Sopenharmony_ci support several Virtual Functions (VFs). Registers in the PF's SR-IOV 1678c2ecf20Sopenharmony_ci Capability control the number of VFs and whether they are enabled. 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci When VFs are enabled, they appear in Configuration Space like normal 1708c2ecf20Sopenharmony_ci PCI devices, but the BARs in VF config space headers are unusual. For 1718c2ecf20Sopenharmony_ci a non-VF device, software uses BARs in the config space header to 1728c2ecf20Sopenharmony_ci discover the BAR sizes and assign addresses for them. For VF devices, 1738c2ecf20Sopenharmony_ci software uses VF BAR registers in the *PF* SR-IOV Capability to 1748c2ecf20Sopenharmony_ci discover sizes and assign addresses. The BARs in the VF's config space 1758c2ecf20Sopenharmony_ci header are read-only zeros. 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci When a VF BAR in the PF SR-IOV Capability is programmed, it sets the 1788c2ecf20Sopenharmony_ci base address for all the corresponding VF(n) BARs. For example, if the 1798c2ecf20Sopenharmony_ci PF SR-IOV Capability is programmed to enable eight VFs, and it has a 1808c2ecf20Sopenharmony_ci 1MB VF BAR0, the address in that VF BAR sets the base of an 8MB region. 1818c2ecf20Sopenharmony_ci This region is divided into eight contiguous 1MB regions, each of which 1828c2ecf20Sopenharmony_ci is a BAR0 for one of the VFs. Note that even though the VF BAR 1838c2ecf20Sopenharmony_ci describes an 8MB region, the alignment requirement is for a single VF, 1848c2ecf20Sopenharmony_ci i.e., 1MB in this example. 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci There are several strategies for isolating VFs in PEs: 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci - M32 window: There's one M32 window, and it is split into 256 1898c2ecf20Sopenharmony_ci equally-sized segments. The finest granularity possible is a 256MB 1908c2ecf20Sopenharmony_ci window with 1MB segments. VF BARs that are 1MB or larger could be 1918c2ecf20Sopenharmony_ci mapped to separate PEs in this window. Each segment can be 1928c2ecf20Sopenharmony_ci individually mapped to a PE via the lookup table, so this is quite 1938c2ecf20Sopenharmony_ci flexible, but it works best when all the VF BARs are the same size. If 1948c2ecf20Sopenharmony_ci they are different sizes, the entire window has to be small enough that 1958c2ecf20Sopenharmony_ci the segment size matches the smallest VF BAR, which means larger VF 1968c2ecf20Sopenharmony_ci BARs span several segments. 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci - Non-segmented M64 window: A non-segmented M64 window is mapped entirely 1998c2ecf20Sopenharmony_ci to a single PE, so it could only isolate one VF. 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci - Single segmented M64 windows: A segmented M64 window could be used just 2028c2ecf20Sopenharmony_ci like the M32 window, but the segments can't be individually mapped to 2038c2ecf20Sopenharmony_ci PEs (the segment number is the PE#), so there isn't as much 2048c2ecf20Sopenharmony_ci flexibility. A VF with multiple BARs would have to be in a "domain" of 2058c2ecf20Sopenharmony_ci multiple PEs, which is not as well isolated as a single PE. 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci - Multiple segmented M64 windows: As usual, each window is split into 256 2088c2ecf20Sopenharmony_ci equally-sized segments, and the segment number is the PE#. But if we 2098c2ecf20Sopenharmony_ci use several M64 windows, they can be set to different base addresses 2108c2ecf20Sopenharmony_ci and different segment sizes. If we have VFs that each have a 1MB BAR 2118c2ecf20Sopenharmony_ci and a 32MB BAR, we could use one M64 window to assign 1MB segments and 2128c2ecf20Sopenharmony_ci another M64 window to assign 32MB segments. 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci Finally, the plan to use M64 windows for SR-IOV, which will be described 2158c2ecf20Sopenharmony_ci more in the next two sections. For a given VF BAR, we need to 2168c2ecf20Sopenharmony_ci effectively reserve the entire 256 segments (256 * VF BAR size) and 2178c2ecf20Sopenharmony_ci position the VF BAR to start at the beginning of a free range of 2188c2ecf20Sopenharmony_ci segments/PEs inside that M64 window. 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci The goal is of course to be able to give a separate PE for each VF. 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci The IODA2 platform has 16 M64 windows, which are used to map MMIO 2238c2ecf20Sopenharmony_ci range to PE#. Each M64 window defines one MMIO range and this range is 2248c2ecf20Sopenharmony_ci divided into 256 segments, with each segment corresponding to one PE. 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci We decide to leverage this M64 window to map VFs to individual PEs, since 2278c2ecf20Sopenharmony_ci SR-IOV VF BARs are all the same size. 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci But doing so introduces another problem: total_VFs is usually smaller 2308c2ecf20Sopenharmony_ci than the number of M64 window segments, so if we map one VF BAR directly 2318c2ecf20Sopenharmony_ci to one M64 window, some part of the M64 window will map to another 2328c2ecf20Sopenharmony_ci device's MMIO range. 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci IODA supports 256 PEs, so segmented windows contain 256 segments, so if 2358c2ecf20Sopenharmony_ci total_VFs is less than 256, we have the situation in Figure 1.0, where 2368c2ecf20Sopenharmony_ci segments [total_VFs, 255] of the M64 window may map to some MMIO range on 2378c2ecf20Sopenharmony_ci other devices:: 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci 0 1 total_VFs - 1 2408c2ecf20Sopenharmony_ci +------+------+- -+------+------+ 2418c2ecf20Sopenharmony_ci | | | ... | | | 2428c2ecf20Sopenharmony_ci +------+------+- -+------+------+ 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci VF(n) BAR space 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci 0 1 total_VFs - 1 255 2478c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2488c2ecf20Sopenharmony_ci | | | ... | | | ... | | | 2498c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci M64 window 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci Figure 1.0 Direct map VF(n) BAR space 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci Our current solution is to allocate 256 segments even if the VF(n) BAR 2568c2ecf20Sopenharmony_ci space doesn't need that much, as shown in Figure 1.1:: 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci 0 1 total_VFs - 1 255 2598c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2608c2ecf20Sopenharmony_ci | | | ... | | | ... | | | 2618c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci VF(n) BAR space + extra 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci 0 1 total_VFs - 1 255 2668c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2678c2ecf20Sopenharmony_ci | | | ... | | | ... | | | 2688c2ecf20Sopenharmony_ci +------+------+- -+------+------+- -+------+------+ 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci M64 window 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci Figure 1.1 Map VF(n) BAR space + extra 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci Allocating the extra space ensures that the entire M64 window will be 2758c2ecf20Sopenharmony_ci assigned to this one SR-IOV device and none of the space will be 2768c2ecf20Sopenharmony_ci available for other devices. Note that this only expands the space 2778c2ecf20Sopenharmony_ci reserved in software; there are still only total_VFs VFs, and they only 2788c2ecf20Sopenharmony_ci respond to segments [0, total_VFs - 1]. There's nothing in hardware that 2798c2ecf20Sopenharmony_ci responds to segments [total_VFs, 255]. 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci4. Implications for the Generic PCI Code 2828c2ecf20Sopenharmony_ci======================================== 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ciThe PCIe SR-IOV spec requires that the base of the VF(n) BAR space be 2858c2ecf20Sopenharmony_cialigned to the size of an individual VF BAR. 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ciIn IODA2, the MMIO address determines the PE#. If the address is in an M32 2888c2ecf20Sopenharmony_ciwindow, we can set the PE# by updating the table that translates segments 2898c2ecf20Sopenharmony_cito PE#s. Similarly, if the address is in an unsegmented M64 window, we can 2908c2ecf20Sopenharmony_ciset the PE# for the window. But if it's in a segmented M64 window, the 2918c2ecf20Sopenharmony_cisegment number is the PE#. 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ciTherefore, the only way to control the PE# for a VF is to change the base 2948c2ecf20Sopenharmony_ciof the VF(n) BAR space in the VF BAR. If the PCI core allocates the exact 2958c2ecf20Sopenharmony_ciamount of space required for the VF(n) BAR space, the VF BAR value is fixed 2968c2ecf20Sopenharmony_ciand cannot be changed. 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ciOn the other hand, if the PCI core allocates additional space, the VF BAR 2998c2ecf20Sopenharmony_civalue can be changed as long as the entire VF(n) BAR space remains inside 3008c2ecf20Sopenharmony_cithe space allocated by the core. 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ciIdeally the segment size will be the same as an individual VF BAR size. 3038c2ecf20Sopenharmony_ciThen each VF will be in its own PE. The VF BARs (and therefore the PE#s) 3048c2ecf20Sopenharmony_ciare contiguous. If VF0 is in PE(x), then VF(n) is in PE(x+n). If we 3058c2ecf20Sopenharmony_ciallocate 256 segments, there are (256 - numVFs) choices for the PE# of VF0. 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ciIf the segment size is smaller than the VF BAR size, it will take several 3088c2ecf20Sopenharmony_cisegments to cover a VF BAR, and a VF will be in several PEs. This is 3098c2ecf20Sopenharmony_cipossible, but the isolation isn't as good, and it reduces the number of PE# 3108c2ecf20Sopenharmony_cichoices because instead of consuming only numVFs segments, the VF(n) BAR 3118c2ecf20Sopenharmony_cispace will consume (numVFs * n) segments. That means there aren't as many 3128c2ecf20Sopenharmony_ciavailable segments for adjusting base of the VF(n) BAR space. 313