首先我们来看一下在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设备,系统也不会再去识别它。

linux操作系统中,我们可以通过lspci –v -t命令来查询系统上电阶段扫描到的PCIe设备,执行结果会以一个树的形式列出系统中所有的pcie设备。如下图所示,其中黄色方框中的PCIe设备是北京忆芯科技公司(Bejing Starblaze Technology Co., LTD.)推出的STAR1000系列NVMe SSD主控芯片,图中显示的9d32是Starblaze在PCI-SIG组织的注册码,1000是设备系列号。

STAR1000设备的BDF也可以从上图中找出,其中bus是0x3C,device是0x00,function是0x0,BDF表示为3C:00.0,与之对应的上游端口是00:1d.0。

我们可以通过“lspci –xxx –s 3C:00.0”命令来列出该设备的PCIe详细信息(技术发烧友或数字控请关注该部分)。这些内容存储在PCIe配置空间,它们描述的是PCIe本身的特性。如下图所示(低位地址0x00在最左边),可以看到这是一个非易失性存储控制器,0x00起始地址是PCIe的Vendor ID和Device ID。Class code 0x010802表示这是一个NVMe存储设备。0x40是第一组capability的指针,如果你需要查看PCIe的特性,就需要从这个位置开始去查询,在每组特征的头字段都会给出下一组特性的起始地址。从0x40地址开始依次是power management,MSI中断,链路控制与状态,MSI-X中断等特性组。这儿特别列出了链路特征中的一个0x43字段,表示STAR1000设备是一个x4lane的链接,支持PCIe Gen3速率(8Gbps)。

当然也可以使用lspci –vvv –s 3C:00.0命令来查看设备特性,初学者看到下面的列表也就一目了然了。

Host在枚举设备的同时也会对设备进行配置,每个PCIe设备都会指定一段CPU memory访问空间,从上面的图中我们可以看到这个设备支持两段访问空间,一段的大小是1M byte,另一段的大小是256K byte,系统会分别指定它们的基地址。基地址配置完成以后,Host就可以通过地址来对PCIe memory空间进行访问了。

PCIe memory空间关联的是PCIe设备物理功能,对于STAR1000系列芯片而言,物理功能是NVMe,memory中存放的是NMVe的控制与状态信息,对于NMVe的控制以及工作状态的获取,都需要通过memory访问来实现。

下面以NVMe命令下发为例简单描述PCIe设备的memory访问。NVMe命令下发的基本操作是1)Host写doorbell寄存器,此时使用PCIe memory写请求。如下图所示,host发出一个memory write(MWr)请求,该请求经过switch到达要访问的NVMe SSD设备。

这个请求会被端点设备接收并执行2)NVMe读取命令操作。如下图所示,此时NVMe SSD作为请求者,发出一个memory read(MRd)请求,该请求经过Switch到达Host,Host作为完成者会返回一个完成事物包(CplD),将访问结果返回给NVMe SSD。

这样,一个NVMe的命令下发过程就完成了。同样,NVMe的其他操作比如各种队列操作,命令与完成,数据传输都是通过PCIe memory访问的方式进行的,此处不再详述。

通过上面的描述,相信能够帮助大家了解PCIe的设备枚举和memory空间访问。

[PCIe]PCIe设备在一个系统中是如何发现与访问的相关推荐

  1. PCIe设备在一个系统中是如何发现与访问的

    PCIe设备在一个系统中是如何发现与访问的 硬盘是大家都很熟悉的设备,一路走来,从HDD到SSD,从SATA到NVMe,作为NVMe SSD的前端接口,PCIe再次进入我们的视野.作为x86体系关键的 ...

  2. linux mtd 块设备,Linux系统中/dev/mtd与/dev/mtdblock的区别,即MTD字符设备和块设备的区别...

    转:http://www.crifan.com/linux_system_in__dev__mtd_and__dev__mtdblock_distinction_character_devices_a ...

  3. win10网络邻居看到linux,在Deepin 20系统中网络共享Windows无法访问的另类解决方法...

    本文在Deepin 20系统中实现网络共享Windows,但无法访问,以下是另类的解决方法之一. 系统环境 共享主机:Deepin 20. 访问共享:Windows7\10家庭版或专业版. 配置和出现 ...

  4. 在Linux系统中允许或拒绝SSH访问特定用户或组的方法

    openSSH默认配置文件有两个指令,允许和拒绝对特定用户或组的SSH访问,本文所要介绍的内容是允许或拒绝在Linux系统中对特定用户或组的SSH访问.一旦我们将用户置于限制模式,他就无法做任何事情, ...

  5. 服务器pcie 3.0装固态硬盘,PCIe SSD怎么装系统?实操发现竟然这么简单!

    [PConline 杂谈]最近有不少小伙伴问某冬,他们自己买了个PCIe SSD,不知道怎么装系统.如果一个人问还好,但是如果很多人问同样的问题,那某冬索性写个PCIe SSD装系统的教程给大家看好了 ...

  6. 从Hadoop看普通算法在一个系统中的应用

    之前看了一些简单的算法题目,感觉很有意思,而在自己做的工程项目开发过程中,却又感觉很少用到,大约是所做的工程太过于简单的缘故吧.最近在读<Hadoop权威指南>那本书,从中看到了不少算法的 ...

  7. 视频监控系统中H.265、SVAC、GB/T28181、ONVIF、PSIA有什么区别?

    说H.265之前我们先要弄清H.264, H.264是ITU-T以H.26x系列为名称命名的视频编解码技术标准之一.国际上制定视频编解码技术的组织有两个,一个是"国际电联(ITU-T)&qu ...

  8. 文读懂安防视频监控系统中H.265、SVAC、GB/T28181、ONVIF、PSIA的区别。

    概览 H.265是和H.26x/MPEG-x AVC一样是一种编码压缩的技术,其具体高效率的编码方式. SVAC<安全防范监控数字视音频编解码技术标准>是国家规范化的编码方式,安全防范监控 ...

  9. 从程序员的角度,来拆解物联网系统中的开发工作

    文章目录 **物联网系统** **设备端的开发** 1. 不需要网关的设备 2. 需要网关的设备 3. WiFi 类设备 **物联网平台开发** **业务应用开发** 推荐一篇好文:从程序员的角度,来 ...

最新文章

  1. 从零开始制作自己的podspec
  2. 初学者怎样看懂python代码_Python零基础入门-(如何让人读懂你的代码)文档注释
  3. vs显式导入(代码注入)依赖库
  4. 稳定排序与不稳定排序的定义
  5. lstm不收敛_20道深度学习面试题,有你不知道的吗?
  6. vue --- http拦截,登录登出的逻辑设计
  7. json数组传递到后台controller
  8. 首席赚钱省钱专家小程序1.5.8+前端
  9. 教你用Python 编写 Hadoop MapReduce 程序
  10. 添加库文件_PLC|教你把 Micro/WIN 的库文件导入到 Micro/WIN SMART 中
  11. C++ map()和pair()用法
  12. 2012.4.19总结(二)
  13. LinkedHashMap jdk1.8源码解析
  14. 详解MES系统在钢铁企业的应用分析
  15. 服务器系统备份还原到虚拟机,一秒还原,一秒备份,系统重装「新手学识4」虚拟机--时光倒流...
  16. fences卸载_【设置方法】win10系统卸载fences的学习
  17. 计算机wps函数的使用,WPS表格中IF函数使用的技巧
  18. 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查
  19. Excise_day01
  20. 解决“DNS_PROBE_FINISHED_NXDOMAIN”,访问网站打不开问题

热门文章

  1. 【BP靶场portswigger-服务端6】信息泄露漏洞-5个实验(全)
  2. 为什么考研报名显示服务器错误,考研到底有多火?2021年考研预报名第一天,服务器出现“故障”...
  3. 偏导,梯度,Hesse矩阵的一些概念和求函数的极值
  4. 高效办公 1.2 用Python新建Excel文件
  5. CCNA WAN 帧中继
  6. Phonetic symbol 辅音 - 清辅音 -- /k/
  7. 2 Linux内核目录概述
  8. Backup App's data without rooting the phone
  9. Vista发布在即 各版本详情介绍
  10. 苹果一体机您的计算机无法启动,苹果一体机怎么开机_苹果一体机开机无显示该怎么解决...