【精讲】PCIe基础篇——BAR(Base Address Register)详解

本文详细介绍了PCI设备中Base Address Register(BAR)的作用,它用于设备告诉系统软件其地址空间需求。BAR分为Memory和I/O类型,系统软件据此分配适当的地址空间。通过读写BAR寄存器的特定位,可以确定设备的地址空间大小和类型。BIOS和OS内核根据BAR信息为设备分配IO或Memory空间,并确保对齐和预取特性。未使用的BAR会被硬件清零,表示不可操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么需要BAR

        系统中的每个设备中,对地址空间的大小和访问方式可能有不同的需求,例如,一个设备可能有256字节的内部寄存器/存储,应该可以通过IO地址空间访问,而另一个设备可能有16KB的内部寄存器/存储,应该可以通过基于MMIO的设备访问。哪些地址应该使用哪种方式(IO或Memory)来访问它们的内部位置,这是系统软件(即BIOS和OS内核)的工作。因此设备必须为系统软件提供一种方法来确定设备的地址空间需求。这种需求就是是通过配置空间头部中的Base Address register (BAR)实现的。一旦系统软件知道设备在地址空间方面的需求,系统软件将分配一个适当类型(IO, NP-MMIO或P-MMIO)的可用地址范围给该设备。如下图所示,Type 0报头有6个bar可用(每个bar的大小为32位),而Type 1头只有2个bar可用。Type 1报头在所有网桥设备中都可以找到,这意味着每个switch端口都有Type 1报头。Type 0报头在非网桥设备中,比如end point。

 二、BAR详解

图1 是Memory BAR寄存器的结构,图2是IO类型的BAR寄存器

 图1 Base Address Register for Memory

图2  Base Address Register for I/O

bit0:表示设备寄存器是映射到memory(0)还是IO(1)空间。
bit1: reserved 0
bit2: 在base adress register for Memory 中0表示32位地址空间,1表示64位地址空间。
bit3:在memory BAR中用来表示该设备是否允许prefetch,1表示可以预取,0表示不可以预区。
bit4~31:用来表示设备需要占用的地址空间大小。

        针对bit4~31,某些位为只读,且0来表示需要的地址空间大小,比如一个PCI设备需要占用1MB的地址空间,那么这个BAR就需要实现高12bit是可读写的,而20-4bit是只读且为0。地址空间大小的计算方法如下:

a.向BAR寄存器写全1

b.读回寄存器里面的值,然后clear 上图中特殊编码的值,(IO 中bit0,bit1, memory中bit0-3)。

c.对读回来的值取反,加一就得到了该设备需要占用的地址内存空间。

        Bios可以为设备预留大于BAR要求的地址空间,而PCI规范中建议为需要的地址空间少于4KB的设备分配4KB的地址空间。映射到IO空间的设备每个BAR不能占用大于256byte,在X86系统中IO编址是16位的,此时BAR中的高16bit需要hardware to zero。构造完成以后需要为设备分配地址空间,此时就是把分配给设备的起始地址写入BAR寄存器即可。我们发现PCI这种地址自然地要求为设备分配的地址空间要跟BAR定义的大小对齐,因此PCI设备的映射空间始终是跟BAR的大小对齐的。

        如果某个设备的BAR没有被全部使用,则对应的BAR应被硬件全被设置为0,并且告知软件这些BAR是不可以操作的。对于被使用的BAR来说,其部分低比特位是不可以被软件操作的,只有其高比特位才可以被软件操作。而这些不可操作的低比特决定了当前BAR支持的操作类型和可申请的地址空间的大小。

        一旦BAR的值确定了(Have been programmed),其指定范围内的当前设备中的内部寄存器(或内部存储空间)就可以被访问了。当该设备确认某一个请求(Request)中的地址在自己的BAR的范围内,便会接受这请求

<think>嗯,用户想了解PCIe BAR的相关概念和配置方法。首先,我需要回忆一下关于PCIe的基本知识。PCIeBAR是用来配置设备地址空间的寄存器,每个设备可能有多个BAR,每个BAR对应不同的内存区域。 首先,应该解释BAR的作用,比如它定义了设备在系统内存中的地址范围,这样CPU和操作系统才能访问设备的寄存器或内存。然后需要提到BAR的配置过程,比如在系统启动时,固件会遍历PCIe设备,读取BAR的大小和类型,然后分配适当的地址空间。 接下来,可能还需要区分不同类型的BAR,比如32位和64位,内存映射和I/O映射的区别。此外,配置步骤可能包括探测BAR的大小,通过向BAR写入全1然后读取回的值来确定所需的内存大小。然后系统会分配一个合适的基地址,并将这个地址写回BAR。 用户可能还想知道具体的配置方法,比如在Linux系统中如何查看BAR的信息,或者驱动程序如何与BAR交互。需要确保引用相关的参考资料,比如引用的[1]和[2],特别是关于HECBASE和系统地址映射初始化的部分。 另外,用户提到的参考资料中有关于系统地址映射初始化的步骤,这涉及到固件在启动过程中处理BAR的配置,步骤3c和12,这可能需要在回答中提及,以说明BAR配置在系统启动中的重要性。 还需要注意技术细节的正确性,比如BAR的位字段结构,例如最低几位表示类型和可预取性。可能需要举例说明如何计算BAR的大小,比如写入0xFFFFFFFF,然后读取得到的值取反加一得到大小。 最后,生成的相关问题需要涵盖BAR的作用、配置步骤、类型区别以及实际应用中的注意事项,帮助用户深入理解。</think>### PCIe Base Address RegisterBAR详解 PCIe设备的**Base Address RegisterBAR)**用于定义设备在系统内存或I/O空间中的地址映射范围,是设备与主机通信的核心机制[^2]。 #### 1. BAR的作用 - **地址分配**:每个BAR对应设备的一段寄存器或内存空间,系统通过BAR为其分配物理地址。例如,一个网卡的寄存器组可能通过BAR映射到内存地址`0xFE000000`[^1]。 - **资源隔离**:不同设备的BAR地址范围互不重叠,避免冲突。 #### 2. BAR的结构 BAR为32位或64位寄存器,其格式如下: $$ \text{BAR} = \begin{cases} \text{bit 0: 类型标识(0=内存,1=I/O)} \\ \text{bit 2-1: 内存类型(32/64位)} \\ \text{bit 3: 是否可预取} \\ \text{bit N-4: 基地址(对齐要求)} \end{cases} $$ 例如,64位可预取内存的BAR最低4位为`0b1100`[^1]。 #### 3. BAR配置步骤 1. **探测空间需求** 系统向BAR写入全1(`0xFFFFFFFF`),读取返回值。例如,返回`0xFFF00000`表示需要$2^{20}=1\text{MB}$空间(取反后加1)[^2]。 ```c // 伪代码示例 write_bar(0xFFFFFFFF); size = ~read_bar() + 1; ``` 2. **地址分配** 系统根据探测结果分配对齐的物理地址,如分配`0xFE000000-0xFE0FFFFF`给1MB的BAR。 3. **写入基地址** 将分配地址按位对齐后写入BAR。例如,将`0xFE000000`写入BAR后,设备寄存器即可通过该地址访问。 #### 4. 实际应用 - **Linux查看BAR**:通过`lspci -vv`命令可查看BAR信息: ``` Region 0: Memory at fe000000 (64-bit, prefetchable) [size=1M] ``` - **驱动开发**:驱动程序通过`ioremap()`将BAR映射到虚拟地址空间后访问硬件寄存器。 #### 5. 注意事项 - **64位BAR**:需要两个相邻的32位寄存器组合实现 - **预取优化**:标记为可预取的BAR允许CPU进行缓存优化[^1] - **虚拟化支持**:需在虚拟化环境中正确传递BAR配置[^3]
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咸鱼弟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值