UEFI学习一:PCIE设备枚举机制

PCI总线简介

       PCI 总线是一个并行总线,一个时钟周期有 32 个 bit (后扩展到 64 bit) 同时传输,带宽 133MB/s ,PCI 设备具有独立的地址空间,叫做 PCI 总线地址空间,通过 Host bridge 隔离处理器系统的存储器域与 PCI 总线域,下面挂在了一个 PCI 总线树,典型的结构如下图:

PCI 总线主要分为三个部分:

  1. PCI 设备。符合 PCI 总线标准的设备就被称为 PCI 设备,PCI 总线架构中可以包含多个 PCI 设备。图中的 Audio、LAN 都是一个 PCI 设备。PCI 设备同时也分为主设备和目标设备两种,主设备是一次访问操作的发起者,而目标设备则是被访问者。
  2. PCI 总线。PCI 总线在系统中可以有多条,类似于树状结构进行扩展,每条 PCI 总线都可以连接多个 PCI 设备/桥,上图中有两条 PCI 总线。
  3. PCI 桥。当一条 PCI 总线的承载量不够时,可以用新的 PCI 总线进行扩展,而 PCI 桥则是连接 PCI 总线之间的纽带,如图的 PCI-to-PCI Bridge 。

        后期为了提高数据传输速率,又推出了 PCIe 总线,改为串行总线,差分信号传输,带宽提升至 250MB/s ,最新的 PCIe 3.0 已经可以达到 8000MB/s 。

       作为x86体系关键的一环,PCIe标准历经PCI,PCI-X和PCIe,走过近30年时光。其中Host发现与查找设备的方式却一脉沿袭,今天我们先来聊一聊PCIe设备在一个系统中是如何发现与访问的。

PCI配置空间

       在 PCI 总线上,通过 Bus number ,Device number 和 Function number 标识每个 PCI 设备,简称 BDF ,每个 PCI 设备内有单独存储空间,叫做 PCI 配置空间。可以通过 IO 端口 CONFIG_ADDRESS 和 CONFIG_DATA 读取 PCI 配置空间。CONFIG_ADDRESS 的地址是 0xCF8,CONFIG_DATA 的地址是 0xCFC,两个寄存器都为 32bit。CONFIG_ADDRESS 寄存器格式:

  • bit31 是使能对 PCI Bus CONFIG_DATA 的访问;
  • bit 30~24 为保留,为只读,访问时返回值为 0;
  • bit 23~16 是Bus号;
  • bit 15~10 是设备号;
  • bit 10~8 是功能号;
  • bit 7~2 是配置空间中的寄存器,单位为 DWORD;
  • bit 1~0 为只读,读取时放回为0。

直接操作 IO 端口读取 PCI 配置信息分为两步:

  1. 向 CONFIG_ADDRESS 寄存器写入要读/写的位置;
  2. 从CONFIG_DATA寄存器(端口0xCFC)读/写所需要数据。

配置空间共 256 字节(地址 0x00~0xFF), 前 64 字节(地址 0x00~0x3F )是所有 PCI 设备必须支持的:

       配置空间都是小端存储。Vendor ID 是厂商 ID ,为保证唯一性,需要设备厂商向 PCI SIG 申请获得,Device ID 由厂商自定义。 Base Address Registers (BAR)用来定义该设备占用的 Memory/IO 空间的类型、起始地址和大小,PCI 设备做多有六个 BAR,PCI 桥最多有两个 BAR 。BAR 在 bit0 来表示该设备是映射到 memory 还是 IO,bar 的 bit0 是 readonly 的,也就是说,设备寄存器是映射到 memory 还是 IO 是由设备制造商决定的,其他人无法修改。空间的大小可以用如下方法读取:

  1. 向寄存器写 0xFFFFFFFF;
  2. 读出寄存器的值,并取反;
  3. 再加 1 就是该空间的大小。

BAR寄存器的结构图:

       PCI 枚举是个不断递归调用发现新设备的过程,系统启动时, 从 Host Bridge 开始寻找设备和桥。发现桥后设置 Bus,会发现一个 PCI 设备子树,递归的过程中,BIOS/UEFI (或者 Linux 内核, 如果配置成这样)与每个 PCI 设备进行配置交易, 为其分配安全的地址空间和中断等资源。在整个过程结束后,一颗完整的资源分配完毕的树就建立好了。

      PCIe 规范在 PCI 规范的基础上,将配置空间扩展到 4KB。原来的 CF8/CFC 方法仍然可以访问所有PCIe设备配置空间的头255B,但是该方法访问不了剩下的(255-4k)配置空间。

PCIe设备枚举机制

       首先我们来看一下在x86系统中,PCIe是什么样的一个体系架构。下图是一个PCIe的拓扑结构示例,PCIe协议支持256个Bus, 每条Bus最多支持32个Device,每个Device最多支持8个Function,所以由BDF(Bus,device,function)构成了每个PCIe设备节点的身份证号。

        PCIe体系架构一般由root complex,switch,endpoint等类型的PCIe设备组成,在root complex和switch中通常会有一些embeded endpoint(这种设备对外不出PCIe接口)。这么多的设备,CPU启动后要怎么去找到并认出它们呢? Host对PCIe设备扫描是采用了深度优先算法,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。我们一般称这个过程为PCIe设备枚举。枚举过程中host通过配置读事物包来获取下游设备的信息,通过配置写事物包对下游设备进行设置。

        第一步,PCI Host主桥扫描Bus 0上的设备(在一个处理器系统中,一般将Root complex中与Host Bridge相连接的PCI总线命名为PCI Bus 0),系统首先会忽略Bus 0上的embedded EP等不会挂接PCI桥的设备,主桥发现Bridge 1后,将Bridge1 下面的PCI Bus定为 Bus 1,系统将初始化Bridge 1的配置空间,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成0和1,以表明Bridge1 的上游总线是0,下游总线是1,由于还无法确定Bridge1下挂载设备的具体情况,系统先暂时将Subordinate Bus Number设为0xFF。

       第二步,系统开始扫描Bus 1,将会发现Bridge 3,并发现这是一个switch设备。系统将Bridge 3下面的PCI Bus定为Bus 2,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成1和2,和上一步一样暂时把Bridge 3 的Subordinate Bus Number设为0xFF。

       第三步,系统继续扫描Bus 2,将会发现Bridge 4。继续扫描,系统会发现Bridge下面挂载的NVMe SSD设备,系统将Bridge 4下面的PCI Bus定为Bus 3,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成2和3,因为Bus3下面挂的是端点设备(叶子节点),下面不会再有下游总线了,因此Bridge 4的Subordinate Bus Number的值可以确定为3。

       第四步,完成Bus 3的扫描后,系统返回到Bus 2继续扫描,会发现Bridge 5。继续扫描,系统会发现下面挂载的NIC设备,系统将Bridge 5下面的PCI Bus设置为Bus 4,并将该桥的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成2和4,因为NIC同样是端点设备,Bridge 5的Subordinate Bus Number的值可以确定为4。

       第五步,除了Bridge 4和Bridge 5以外,Bus2下面没有其他设备了,因此返回到Bridge 3,Bus 4是找到的挂载在这个Bridge下的最后一个bus号,因此将Bridge 3的Subordinate Bus Number设置为4。Bridge 3的下游设备都已经扫描完毕,继续向上返回到Bridge 1,同样将Bridge 1的Subordinate Bus Number设置为4。

       第六步,系统返回到Bus0继续扫描,会发现Bridge 2,系统将Bridge 2下面的PCI Bus定为Bus 5。并将Bridge 2的Primary Bus Number 和 Secondary Bus Number寄存器分别设置成0和5, Graphics card也是端点设备,因此Bridge 2 的Subordinate Bus Number的值可以确定为5。

       至此,挂在PCIe总线上的所有设备都被扫描到,枚举过程结束,Host通过这一过程获得了一个完整的PCIe设备拓扑结构。

       系统上电以后,host会自动完成上述的设备枚举过程。除一些专有系统外,普通系统只会在开机阶段进行进行设备的扫描,启动成功后(枚举过程结束),即使插入一个PCIe设备,系统也不会再去识别它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值