当前位置: 首页 > news >正文

【PCI】PCI设备访问及配置过程、虚拟PCIe switch方案(六)

PCI设备怎样访问

我们知道内存访问由CPU发出访问地址就可直接访问,如下图所示。

那增加PCI设备之后如何访问PCI设备呢?如下图所示。

CPU发出的地址既可以送去内存控制器,也可以送去host主桥。那么,哪些地址送去哪由什么来决定?也就是说,哪些地址是给PCI设备使用的?

继续看下图。

以X86为例,称CPU所能寻址的空间为存储器域,DRAM控制器所能访问的地址空间集合成为DRAM域,PCI设备设备所能直接访问的地址空间成为PCI总线域。

CPU访问DRAM或者PCI设备时,首先需要访问存储器域的地址,这些发送到存储器域的数据请求首先通过地址转换部件,并由地址转换部件决定这些数据请求是发向PCI总线域、DRAM域还是其他域空间。注意,这个地址转换部件是一个芯片设计中的概念,而不是某个具体的实体。

那么X86中存储器域的地址空间是如何划分的呢?看下图。

如上图所示,X86处理器将存储器域划分为若干部分,分别映射到DRAM域和PCI总线域,由于背负历史包袱,空间划分显得十分怪异。

由上可知道当CPU访问红框内空间时,地址转换部件将CPU的请求送给HOST主桥或RC译码,进而读写PCI总线域上地址空间。

那么问题来了,这些红框内空间怎么和设备对应呢?提前给每个设备定义好地址区间?

实际使用时,每个pci设备需要的内存空间不一样(有大有小甚至不使用),所以很难做到提前给设备划分PCI总线空间。因此系统采用的是动态按需分配方法:BIOS在启动阶段会枚举所有PCI设备,根据PCI设备的需求给每个PCI设备分配PCI总线空间,并将空间基地址配置给设备,这样一来设备就知道应该监听哪段地址空间,后续CPU访问想要访问哪个PCI设备,就去访问对应分配的PCI总线空间即可(设备监听到给与响应)。

那么,问题又来了,怎么选中PCI设备获取它的需求并给它配置PCI总线空间呢?

PCI设备如何配置

X86处理器定义了两个I/O端口寄存器,分别为CONFIG_ADDRESS何CONFIG_DATA寄存器,器地址为0xCF8和0xCFC。这两个寄存器如何使用呢?简单来说就是把需要访问的PCI设备信息按特定格式写入CONFIG_ADDRESS(0xCF8)寄存器,然后读写CONFIG_DATA(0xCFC)寄存器即可。

CONFIG_ADDRESS寄存器信息格式如下。

  • Enable位,第31位。该位为1时,对CONFIG_DATA寄存器进行读写时将引发PCI总线的配置周期。
  • Bus Number字段,第23~16位,记录PCI设备的总线号,每个pci桥扩展出来的信号总线编号,最多256个总线号,host主桥出来的是0号。
  • Device Number字段,第15~11位,记录PCI设备的设备号,每个总线编号下的设备编号,最多32个设备号,从0开始。
  • Function Number字段,第10~8位,记录PCI设备的功能号,设备内部实现的功能编号,最多8个,从0开始。

将PCI设备的总线号、设备号、功能号以及寄存器号填写到CONFIG_ADDRESS寄存器并使能第31位,然后读写CONFIG_DATA寄存器即可读写指定PCI设备的指定寄存器了。所以对PCI设备的某些寄存器读写,就可以获取PCI设备空间需求并配置空间基地址了!

问题又来了,PCI设备的总线号、设备号、功能号以及寄存器号怎么来?PCI设备怎么知道这些信息呢?

功能号和寄存器号是设备内部实现的(按规范),设备自己知道这些信息。PCI总线号是给PCI桥设备(特殊的PCI设备)使用的(路由),普通的PCI设备不会使用,后面会介绍由来和使用方法。PCI设备号由IDSEL信号线与ADx信号线连线决定的(就如单片机访问外设先CS片选一样),先看下图。

AD31~AD0信号是地址和数据复用引脚,在地址周期上传输地址,在数据周期传输数据。IDSEL是PCI设备片选信号,只有选中了PCI设备才会响应配置请求。

PCI总线规定配置访问有两种方式,分别为type0和type1,先看一下type0访问,如下图所示。

CPU对host主桥下面直连设备进行配置时,由host主桥将CONFIG_ADDRESS寄存器部分信息放到AD31AD0信号线上,放置关系如上图所示,CONFIG_ADDRESS的[10-2]bit位将原样拷贝到AD2AD10信号线上(AD1~AD0必须为0表示type0配置),而CONFIG_ADDRESS的Device Number字段则按数字对应到AD11~AD31信号线上,即访问某个设备号就将对应的bit位置1,其每一位对应选通一个PCI设备(其实就是将设备的IDSEL信号线与ADx线相连)。注意,Device Number最大可以为31(表示第32个设备,0为第一个),但AD11~AD31只有22位,所以只能对应22个设备号,对应关系由桥决定。示例图如下。

如上图,假设host主桥将021设备号对应AD11AD31信号线,那么设备A的device number就是0,称设备A为0号总线上第0号设备。BIOS枚举0号总线上设备的过程就是依次拉AD11~AD31信号选中对应设备,读取设备的Header Type寄存器(0x00),知道是普通PCI设备后,再读写设备特殊寄存器(bar)获取空间需求并设置空间基地址。

那么,桥设备及桥下设备怎么配置呢?看下图。

host主桥拉AD11信号线选中设备A,再读取设备的Header Type寄存器(0x01),发现是PCI桥设备,然后便去设置桥设备A的primary bus寄存器为0、secondary bus寄存器为1、subordinate bus寄存器为1(桥A下无桥),这样桥设备A就知道监听的总线范围为secondary bus(1)~subordinate bus(1)。host主桥发现设备A是桥设备后,会去遍历桥A下bus 1总线上挂载的设备,由于设备B不是直连host主桥,因此host主桥将发送type1的配置请求到bus 0上,格式如下。

如上图所示,host主桥将CONFIG_ADDRESS寄存器除了第31位使能位外的内容拷贝到AD总线上,并将[1:0]设置为0b01表示type1配置请求。

桥设备A发现bus 0上存在type1配置请求,并且AD16~AD23的Bus Numver(1)与自身secondary bus(1)寄存器相等,便接受这个type1请求,并转换成type0请求发到bus 1总线上,也就是拉AD信号线选中设备。当设备B被选中后,读取设备B的Header Type寄存器(0x00),知道是普通PCI设备后,再读写设备特殊寄存器(bar)获取空间需求并设置空间基地址,最后host主桥会将给设备B分配的PCI总线空间基地址及大小填写到桥设备A的memory base、memory limit等寄存器中。

为什么要将给设备B分配的PCI总线空间基地址及大小填写桥设备A的memory base、memory limit等寄存器呢?看下图。

对PCI设配配置的目的就是为它们分配PCI总线空间,进而让它们知道自己应该监听响应哪些PCI地址空间访问。以上图为例,当CPU读写存储器域地址0x9a100000~0x9a10ffff之间区域时,地址转换部件发现这个地址区域是属于PCI总线空间的,因此将访问请求送给host主桥,由host主桥将访问请求转成TLP mem读/写请求放到bus 0上,bus 0上的设备C监听到这个请求地址落在自己范围内,便响应CPU的读写请求。当CPU读写储器域地址0x9a000000~0x9a00ffff之间区域时,host主桥将访问请求转成TLP mem读/写请求放到bus 0上,bus 0上的桥设备A发现地址落在memory base~memory base+memory limit范围内,则接受这请求并转发到bus 1,bus 1上的设备B监听到这个请求地址落在自己范围内,便响应CPU的读写请求。所以桥设备的memory base、memory limit等寄存器也是为了路由用的。

综上可以知道以下信息:

  • PCI设备号由两个因素决定:1.PCI设备的IDSEL信号线与具体的哪个ADx信息连接;2.桥如何将AD11~AD31与device number对应。
  • PCI桥必须先由type0配置完primary bus、secondary bus、subordinate bus等寄存器后,才能路由type1请求。
  • PCI总线号给PCI桥使用,主要让pci桥设备能监听配置请求type1,并根据type1里面的bus number和自身secondary bus、subordinate bus寄存器对比,决定是否路由type1请求。
  • PCI桥设备的memory base、memory limit等寄存器是为了路由TLP mem读/写请求。
  • PCI设备必须通过type0配置完bar寄存器之后(获得PCI总线空间基地址),才能响应CPU的数据读写请求。

虚拟pcie-switch

在介绍虚拟pcie switch之前,先看看物理pcie switch的功能。

物理pcie-switch


pcie switch和其他物理总线switch一样,都是将一条总线扩展成多条总线。

由之前所述并结合上图可以知道上图的物理pcie switch应该具备以下能力:

  • 上图pcie swicth内部有4个bridge,所以这个pcie switch需要提供4组bridge配置寄存器,即4个桥配置空间。
  • 从宏观来看,pcie switch需要接受CPU对内部4个bridge和下面3个PCI设备的所有请求(配置请求、数据读写请求)。对于发送给bridge的请求,应该在switch内部消化掉。对于发送给下面设备的请求,应该转发给对应设备。
  • 数据优先级处理能力,如bus 3下设备和bus 4下设备同时访问RC时,谁的数据先通过switch的upstream port口。

虚拟pcie-switch方案

假如我们有一个PCIe设备有4个function,如下图所示,PCIe设备4个function共用一个EP PCIe IP资源接口,如何将4个function拆分成4个PCIe设备?

如果这个PCIe设备内部真正实现了物理switch,那么资源应该如下图所示。

上图在原本的PCIe设备内部实现了一个物理上的switch,从而将4个function的PCIe设备拆分成为4个PCIe设备,但这样将会额外增加很多硬件资源。

那么,如何在改动最小且占用资源最少的情况下将单个设备拆分成4个设备?

在物理pcie-switch部分说道:“从宏观来看,pcie switch需要接受CPU对内部4个bridge和下面3个PCI设备的所有请求(配置请求、数据读写请求)。对于发送给bridge的请求,应该在switch内部消化掉。对于发送给下面设备的请求,应该转发给对应设备”。其实也就是所有访问switch内部及外界设备的请求,都必须由switch顶端的bridge接收并转发,根据这个规律,可以设计下图方案。

上图左侧为实际资源视图,来看看是如何工作的。

枚举过程:

  • BIOS枚举时,发现Bridge A下面是一个桥设备B,因此会设置Bridge B的primary bus numberj寄存器为1,secondary bus number寄存器为2,subordinate bus number寄存器暂为0xff;
  • BIOS配置完桥设备B后将会扫描bus 2(虚拟总线)上设备,由于不是直连RC,所以RC发出type1(bus=2,dev=0)配置请求到bus 1上,再由Bridge B捕获送到辅助处理器上;
  • 辅助处理器内存上维护着4个Bridge配置空间和4个ep配置空间,当Bridge B送来的type1(bus=2,dev=0)配置请求时,辅助处理器组装消息告诉RC——“bus 2上的设备0是一个桥设备bridge0”。因此BIOS将设置Bridge0的primary bus numberj寄存器为2,secondary bus number寄存器为3,subordinate bus number寄存器暂为0xff;
  • BIOS配置完Bridge0后将会扫描bus 3上设备,由于不是直连RC,所以RC发出type1(bus=3,dev=0)配置请求到bus 1上,再由Bridge B捕获送到辅助处理器上;
  • 辅助处理器组装消息告诉RC——“bus 3上的设备0是一个PCIe设备ep0”。因此BIOS将读写ep0的bar寄存器获取空间需求,然后为其分配空间(假设为0x9a000000~0x9a000100),并将pci总线空间基地址写入bar;
  • BIOS配置完ep0后继续扫描bus 3上设备,依次发出type1(bus=3,dev=1~31)请求,由Bridge B捕获送到辅助处理器上,但辅助处理器不给予回复,这样RC就认为Bridge0上只有一个ep0设备,然后将Bridge0的subordinate bus number寄存器修改为3;
  • 接着BIOS返回扫描bus 2上设备,RC发出type1(bus=2,dev=1)配置请求到bus 1上,再由Bridge B捕获送到辅助处理器上;
  • 辅助处理器组装消息告诉RC——“bus 2上的设备1是一个桥设备bridge1”…(后续处理过程与上面一样);
  • Bridge B下所有设备扫描完后,BIOS将修改Bridge B的subordinate bus number寄存器暂为6(路由使用),Memory Base寄存器设置为0x9a000000,Memory Limit寄存器设置为0x9a0003ff(忽略最小限制);
  • 最终,Host主机就会认为Bridge B下游4个Bridge桥,每个桥下有一个ep设备,也就是上图右侧Host主机视图。

数据读写:

  • CPU读写存储器域上0x9a000050地址时,地址转换部件发现地址落在PCI总线空间区域上,因此将读写请求转发给RC,由RC译码成TLP mem读/写请求放到bus 1上;
  • Bridge B发现bus 1上的TLP mem读/写请求地址0x9a000050在Memory Base~Memory Base+Memory Limit区间内,所以接受请求送给辅助处理器;
  • 辅助处理器发现0x9a000050地址是属于ep0的,然后将其送给Function 0,再由Function 0响应CPU的读写请求。

可以看到,上述方案可以实现将4个function的PCIe设备拆分成4个PCIe设备,但并不完美。仔细分析一下可以发现,对于配置过程来说,辅助处理器必须参与,因为配置空间都是维护在辅助处理器的内存中,但对于数据读写过程来说,辅助处理器只是判断了一下读写地址落在哪个ep上,然后送给对应的function就好了,所以,能否建立一个地址与function对应关系表给硬件查就好了?

改进方案如下图。

Bridge B接收到的请求先通过req switch模块路由,如果是配置请求则送给辅助处理器,如果是MRD/MWR请求则查表后送给对应function。上图只是一个粗略方案,实际上还有很多需要完善的。

http://www.jsqmd.com/news/907781/

相关文章:

  • 嘎嘎降AI为什么是性价比首选?2026年降AI率工具TOP10实测
  • MYTHOS-26B-A4B性能优化指南:GPU内存管理与推理速度提升技巧
  • 观察使用taotoken token plan套餐在长期项目中的成本节省效果
  • 2026年5月25-30万家用SUV车型推荐:TOP5排名家庭出行舒适评测专业价格 - 品牌推荐
  • 别再死记硬背三次握手了!用Wireshark抓个包,亲手‘看见’TCP连接全过程
  • 构建面向AI的现代数据湖:核心原则、架构选型与实施指南
  • 2026年靠谱的浙江扫地车/电动扫地车源头工厂推荐 - 行业平台推荐
  • 哪家25-30万五座SUV车型专业?2026年5月推荐TOP5对比家庭出游防空间局促评测案例适用场景 - 品牌推荐
  • 别再只画平面电感了!用ANSYS HFSS玩转TSV三维集成电感,保姆级建模与仿真避坑指南
  • 基于Arduino与超声波传感器的智能安防系统设计与实现
  • 保姆级教程:在PyQt5 Designer里拖拽出你的第一个串口数据监控界面(附QChartView配置)
  • 从循环到函数式:JavaScript数据处理的核心思维转变
  • 告别WMMA API:用PTX的LDMATRIX和MMA指令在Ampere架构上重构你的HGEMM Kernel
  • ARM Cortex-M微控制器MTB技术原理与应用优化
  • 哪家25-30万家用SUV车型专业?2026年5月推荐TOP5对比家庭出游舒适度评测案例价格 - 品牌推荐
  • 2026年门窗开启方式改造阳台门窗维修/隔热阳光房门窗维修优质供应商推荐 - 品牌宣传支持者
  • 如何永久守护你的数字记忆:WeChatMsg聊天记录智能保存完全指南
  • 2026年热门的热熔焊接机/无锡脉冲焊接机深度厂家推荐 - 品牌宣传支持者
  • 深度对话ChatGPT:探索AI创造力边界与高效人机协作实战
  • 2026年5月10款降AI率工具实测:嘎嘎降价格售后双优盘点
  • AI时代职场变革:人机协作、技能重构与未来职业生态
  • 哪家25-30万五座SUV车型值得选?2026年5月推荐TOP10对比试驾乐趣评测案例性价比高 - 品牌推荐
  • 5分钟搞定老旧视频修复!Video2X AI画质增强实战指南
  • 如何免费永久保存微信聊天记录:WeChatMsg隐私保护终极指南
  • 2026年质量好的无锡超声波焊接模具/手持超声波焊接机/无锡超声波焊接/全自动超声波焊接机多家厂家对比分析 - 行业平台推荐
  • 职业倦怠的系统性防御与修复:从能量管理到心理韧性构建
  • 2026年比较好的水果包装箱/快递包装箱/包装箱长期合作厂家推荐 - 行业平台推荐
  • 降AI率软件60块和240块差在哪?2026年TOP10工具价格盘点
  • 用SpringBoot+Vue仿写一个宠物医院系统,我踩过的这些坑你一定要避开
  • SSD卸载对LLM MoE模型能效的影响与优化策略