​PCIe BAR(Base Address Register)详解


BAR(基地址寄存器)​ 是PCIe设备配置空间中的关键部分,用于为设备分配内存或I/O地址空间。以下是其核心概念和工作原理的总结:


1. BAR的作用
  • 地址分配:让操作系统知道设备需要多少地址空间,然后分配相应的物理地址。操作系统通过BAR为设备分配物理地址,使设备能够与CPU通信
  • 资源声明:设备通过BAR告知系统所需的内存或I/O空间大小及类型。

2. BAR的结构
  • 位置:位于PCIe配置空间的标准头部(Header),通常有6个BAR(BAR0-BAR5)。
  • 类型
    类型标志位(Bit 0)说明
    内存空间032位或64位地址映射
    I/O空间1传统I/O地址(现代设备较少使用)

3. BAR的初始化流程
  1. 探测空间大小

    • 向BAR写入全1(0xFFFFFFFF),再读取其值。
    • 计算掩码:size = ~(read_value & 0xFFFFFFF0) + 1
    • 示例:若读回值为0xFFF00000,则掩码为0x000FFFFF,空间大小为 ​1 MB
  2. 分配物理地址

    • 系统根据探测结果分配对齐的物理地址,并写入BAR。

4. 32位与64位BAR
  • 32位BAR:支持最大4 GB地址空间。
  • 64位BAR
    • 使用两个连续的BAR(如BAR0和BAR1)组合。
    • 标志位:Bit 2-1为0b10(64位内存空间)。
    • 示例
      BAR0: 0x00000000 (低32位地址)
      BAR1: 0x80000000 (高32位地址)
      组合地址 = 0x8000000000000000

5. 常见应用场景
  1. 显卡显存映射

    • 使用64位BAR映射大容量显存(如16 GB)。
    • 驱动通过ioremap访问该地址。
  2. NVMe控制器寄存器

    • BAR0映射控制寄存器(如队列门铃、中断配置)。
    • BAR1映射数据缓冲区(若需要)。
  3. 高速网卡DMA区域

    • 通过BAR分配连续物理内存,支持零拷贝数据传输。

6. 关键属性
  • 预取(Prefetchable)​:Bit 3为1时,允许CPU预取数据(适用于显存等频繁访问区域)。
  • 对齐要求:BAR分配的地址必须按空间大小对齐(如1 MB空间需对齐到1 MB边界)。

7. 示例:BAR探测与分配
  1. 设备声明需求
    • BAR0写入全1后读回0xFFFF0000 → 计算空间大小:
      mask = 0xFFFF0000 & 0xFFFFFFF0 = 0xFFFF0000
      size = ~mask + 1 = 0x0000FFFF + 1 = 0x00010000 → 64 KB
  2. 系统分配地址
    • 分配64 KB对齐的物理地址(如0x1FE00000),写入BAR0。

8.BAR的工作过程

BAR的作用是让操作系统知道设备需要多少地址空间,然后分配相应的物理地址。那BAR里面存的是地址吗?好像不是直接存地址,而是通过写入全1来探测所需空间的大小。

比如,当系统启动时,BIOS或操作系统会遍历PCIe设备,读取每个设备的配置空间。当遇到BAR时,会向BAR写入全1(比如0xFFFFFFFF),然后读回数值。根据读回的值,可以判断设备需要的内存或I/O空间的大小和类型。例如,如果低几位是0,那这些位代表地址线,进而可以算出所需空间的大小。比如,一个BAR写入全1后读回0xFFFF0000,那么低16位是0,说明需要64KB的空间?

不过这里可能有个误区,因为不同的BAR类型(内存或I/O)会有不同的格式。内存类型的BAR,最低的几位表示可预取的、地址类型(32位或64位),而I/O类型的BAR则最低位是1。但PCIe设备通常不使用I/O空间,而是使用内存映射的I/O,所以I/O类型的BAR可能较少见。

另外,BAR的数量可能有多个,比如BAR0到BAR5。每个BAR对应不同的资源需求。例如,显卡可能需要一个较大的内存区域来映射显存,而NVMe SSD的控制器可能需要多个BAR来映射不同的寄存器区域。

但具体来说,如何确定一个BAR是32位还是64位的?比如,如果设备需要超过4GB的地址空间,就需要64位的BAR。这时可能需要两个连续的BAR来组成一个64位的地址空间。比如,BAR0是低32位,BAR1是高32位。这种情况下,系统在分配时会识别到这两个BAR是组合使用的,从而分配一个64位的地址范围。

不过,这里可能需要查阅具体的规范。PCIe的配置空间中,每个BAR是32位的,但如果有64位的地址需求,就会使用两个相邻的32位BAR来组成一个64位的地址。这时候第一个BAR的低位会指定这是一个64位的地址空间,而第二个BAR则被保留用于高32位。

比如,当系统探测BAR0时,发现它是一个64位内存类型的BAR,那么就会将BAR0和BAR1合并成一个64位的地址。这时候BAR1就不能单独使用了,必须和BAR0一起使用。所以在设备设计时,如果需要64位地址,就需要保留两个BAR来组成一个64位空间。

另外,BAR的初始化过程是怎样的呢?当系统启动时,操作系统会遍历每个PCIe设备,读取它们的BAR,并写入全1来探测所需空间的大小。然后根据系统的可用地址空间,分配适当的物理地址,并将这个地址写入BAR中。这样,设备就可以通过这个物理地址与系统进行通信了。

举个例子,假设一个设备需要256MB的内存空间,那么系统在探测BAR时,发现写入全1后BAR的值是0xFFF00000,那么低20位是0,说明需要1MB对齐,并且空间大小是1MB?还是说需要更复杂的计算?

哦,可能计算方法是这样的:当向BAR写入全1后,读回的值取反加1,得到的是掩码,然后用这个掩码来确定地址空间的大小。例如,如果BAR是32位的,写入0xFFFFFFFF,读回的是0xFFF00000,那么取反加1得到0x000FFFFF +1 = 0x00100000,也就是1MB的大小。所以设备需要1MB的内存空间。

但是,如果是64位的BAR,可能需要两个32位的寄存器来组合,这时候计算方法可能更复杂。需要将两个BAR的值组合起来,再进行类似的计算。

还有,BAR的地址分配是物理地址,设备通过这个地址直接访问内存,而不需要经过虚拟地址转换。所以,在驱动程序中,通常会将这个物理地址映射到内核的虚拟地址空间,从而让驱动程序能够访问设备的寄存器或内存区域。

不过,这里可能存在一些混淆,比如内存映射的I/O和端口I/O的区别。PCIe设备通常使用内存映射的方式,所以驱动程序通过ioremap之类的函数将BAR中的物理地址映射到内核虚拟地址,然后通过读写这些地址来与设备通信。

总结一下,BAR的作用是让系统为设备分配所需的地址空间,通过写入全1来探测空间的大小,并根据系统的可用地址分配具体的物理地址。每个BAR可以对应内存或I/O空间,而64位的地址需要两个BAR来组合。BAR的数量和设备的需求相关,不同的BAR可能用于不同的功能区域,如控制寄存器、数据缓冲区等。

不过,我可能在某些细节上有误,比如具体的计算方法、BAR的组合方式等,需要查阅PCIe的规范或相关资料来确认。另外,实际中的BAR处理可能还涉及对齐要求、预取属性等更复杂的因素。

9. 常见问题
  • Q1:如何查看设备的BAR分配?

    • Linux:lspci -vvv 显示BAR地址及大小。
    • Windows:设备管理器 → 资源选项卡。
  • Q2:BAR地址冲突怎么办?

    • 检查BIOS/UEFI设置,确保地址空间分配正常。
    • 更新驱动或操作系统补丁。
  • Q3:64位BAR如何支持大内存设备?

    • 系统需支持64位地址映射(如x86_64架构)。
    • 驱动需使用ioremapmmap映射高地址。

10. 总结
  • BAR是PCIe设备与系统通信的桥梁,通过灵活分配内存/I/O空间支持多样化硬件需求。
  • 理解BAR的探测、分配及访问机制,对驱动开发和硬件调试至关重要。

参考:

  1. PCIe 总线基础 驱动接口 和 BAR空间详解_pcie bar空间-优快云博客 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩瀚之水_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值