【问题标题】:How is a PCI / PCIe BAR size determined?PCI / PCIe BAR 大小如何确定?
【发布时间】:2013-09-25 13:42:38
【问题描述】:

我知道 PCI 配置空间中的基地址寄存器 (BAR) 定义了 PCI 地址的起始位置,但是这个区域的大小是如何确定的呢?

这当然是硬件的一个属性,因为只有它知道它可以处理多远的地址空间。但是,我似乎在 PCI 配置结构中看不到 BAR 大小字段。

【问题讨论】:

    标签: pci pci-e


    【解决方案1】:

    首先,BAR 大小必须是 2 的幂(例如,1 KiB,2 MiB),并且每个区域必须在内存中对齐,以使基地址的低 log2(size) 位始终为零。例如,假设一个端点有一个 4 KiB 的内存区域,它给出的地址范围是0-0xfff。宿主可能会将该区域的起点重新映射到 f.x。 0x10000xabcd000 写入 BAR 寄存器,但不写入 0x10800xabcd100

    写入 BAR 寄存器时,端点将忽略 LSB 并在读取时始终返回零。因此将0xffffffff 写入寄存器然后读回该值表示该区域的大小。对于 4 KiB 示例,这将返回 0xfffff00X(低四位保留,请参阅规范)。确定大小:

    • 将低四位清零 (0xfffff000)
    • 反转所有 32 位 (0xfff)
    • 在结果中加一 (0x1000 = 4096 bytes)

    这也适用于 64 位区域。下一个基地址寄存器的值构成基地址的 MSB。 PCI 3.0 规范的第 6.2.5.1 节对此进行了描述。

    【讨论】:

    • 在上面的例子中,为什么写全1(0xFFFFFFFF)到寄存器返回(0xFFFFF00X)?例如,如果地址大小是 4 KiB,它的基地址是 0xabcd000C。不应该将所有 1 写入寄存器返回 0xFFFF000C,因为根据规范,您不能写入 BIOS 尚未设置的位?但我很确定我理解错了^^'你能帮忙解释一下吗?
    • 我想,我现在明白了。如果设备需要 4 KiB 内存区域,则较低的 log2(1024*4) 即 32 位中的 12 位需要为零。如果 BAR 中的值类似于 0xabcde00X,写入全 1 将返回 0xFFFFF000(因为未设置位被硬连线为 0,并且信息位/无关位 (X) 返回为 0。但是,假设我们有一个基地址为 0xabcd000X,地址大小为 4KiB。当我们写全 1 时,硬件如何知道返回 0xFFFFF000?(我假设硬件会返回 0xFFFF0000,因为只设置了前 16 个字节。
    【解决方案2】:

    OSDev Wiki找到答案:

    “要确定 PCI 设备所需的地址空间量,您必须保存 BAR 的原始值,将全 1 的值写入寄存器,然后将其读回。”

    【讨论】:

      【解决方案3】:

      PCIe 设备可以具有 Type-0(端点)或 Type-1(RC 或交换机或桥接器)配置空间。

      --Type-0 设备总共可以有 6 个 BAR,而 Type-1 只能有 2 个 BAR。

      --BAR 给出设备所需的地址空间信息。

      --每个 BAR 都是 32 位的,其中前 4 位 3:0 总是只读的。

      -- 2^(从最低有效位开始的最后一个 R/W 位的位置) = 特定 BAR 所需的地址窗口。

      如何知道任意BAR所代表的区域的地址窗口或大小:

      1) 最初读取任何 BAR(在我们的例子中假设 BAR0),我们得到值 32'h0000_000F。 (记住:最后 4 位只读!!)。

      2) 将所有 1 写入 BAR0。

      3) 再次读取 BAR0 并假设我们得到值 32'hFFFF_000F。所以位位置 16 是最低有效的 R/W 位。所以 BAR0 需要的地址空间为 2^16。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-04
        • 1970-01-01
        • 2014-06-16
        相关资源
        最近更新 更多