天天看点

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

一、为什么需要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。

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

 二、BAR详解

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

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

 图1 Base Address Register for Memory

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

图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的范围内,便会接受这请求

继续阅读