Linux 从CPU将字节写入PCIe地址空间的精确细节

Linux 从CPU将字节写入PCIe地址空间的精确细节,linux,pci-e,Linux,Pci E,我对让CPU将值写入PCIe卡内存所涉及的一系列步骤感到非常困惑。很难理解你在互联网上读到的东西的确切含义,所以我希望有人能阅读我的理论并指出任何错误 安装程序 假设我有一个PCIe卡,上面有一些内存。为了便于讨论,假设以下具体设置: 它有4 MB可通过基址寄存器0访问(无论这意味着什么) 它是整个系统中唯一的PCIe卡 它插入PCIe插槽,该插槽通过主板中的铜线连接到根复合体 有一个根复合体直接连接到CPU的总线(这是正常的连接方式吗?) PCIe卡以某种方式配置为设备编号0(这是如何实现的

我对让CPU将值写入PCIe卡内存所涉及的一系列步骤感到非常困惑。很难理解你在互联网上读到的东西的确切含义,所以我希望有人能阅读我的理论并指出任何错误

安装程序 假设我有一个PCIe卡,上面有一些内存。为了便于讨论,假设以下具体设置:

  • 它有4 MB可通过基址寄存器0访问(无论这意味着什么)
  • 它是整个系统中唯一的PCIe卡
  • 它插入PCIe插槽,该插槽通过主板中的铜线连接到根复合体
  • 有一个根复合体直接连接到CPU的总线(这是正常的连接方式吗?)
  • PCIe卡以某种方式配置为设备编号0(这是如何实现的?)
  • 我们正在使用Linux
让我们再谈谈术语:

  • 系统总线是CPU自己的总线
  • PCIe总线指的是主板上CPU和PCIe插槽之间的文字线
  • 驱动程序是Linux内核模块
  • 设备是一个文本物理对象
  • 设备结构是由内核填充的
    pci\u dev
    结构
  • BAR(基址寄存器)是PCIe设备配置空间内的字段
  • 条形空间是地址空间,由条形中的值表示(?)
我的理论是怎么回事
  • 在启动时,Linux开始探测不同的地址,看看是否有什么

    • 由于PCIe总线导线仅通过网桥(即系统总线上的PCIe控制器)连接到系统总线导线,Linux必须知道如何与PCIe控制器交互
    • Linux向PCIe控制器发送特殊命令(通过内存映射IO?),最终触发PCIe导线上的正确电压系列
    • 如果它得到响应,它将在配置空间中用其他信息填充
      pci_dev
      struct
    • 在将来的某个时候(什么时候?),内核将遍历PCI驱动程序列表,尝试将它们与设备匹配
  • 当Linux检测到一个设备时,它会将其条空间映射到系统总线上。(这是如何实现的?)假设它将BAR0空间映射到系统总线上的地址
    0x55500000
    0x5550FFFF
    • Linux必须告诉根复合体侦听这些地址,并且它们对应于它检测到的PCIe卡
    • 顺便说一句,Linux会将PCIe卡上的基址寄存器0设置为在其基址字段中有
      0x55500000
      (为什么要麻烦?)
  • 0x55500000
    0x5550FFFF
    之间的系统总线上的后续写入被根复合体“捕获”,并发送到PCIe卡
    • 根复合体将基本上构建一个数据包,该数据包将包含所有的报头和校验和等,并通过主板的铜线将它们发送到PCIe插槽
  • 假设CPU将
    0xDEADBEEF
    写入系统总线上的地址
    0x55501230
    ,并且根复合体将数据包发送到PCIe卡,该卡接收数据包并将
    0xDEADBEEF
    写入其本地4 MB内存中的
    0x01230

  • 那么:这其中哪些部分是对的,哪些是错的?

    我的经验是使用英特尔处理器,因此下面的一些细节可能是针对英特尔处理器的,但大部分是通用的。另外,我不知道Linux如何识别每个设备要加载的驱动程序的细节,所以我跳过了这个问题

    现代CPU没有系统总线(除了隐藏在CPU内部)。它们具有内存通道、PCIe根端口和连接到芯片组的DMI端口(也称为外围控制器集线器或PCH)。PCH包含其他设备,并且可能具有其他根端口。根复合体包括集成到CPU和PCH中的电路。(一些CPU SoC没有DMI或PCH,所有根复杂电路都在CPU SoC内。)

    即使您的卡是整个系统中唯一的PCIe卡,也有其他PCIe设备集成到根复合体中(称为RCIEP或根复合体集成端点)。这些可能在CPU或PCH中

    连接到PCIe根端口的设备将在某些非零总线号上配置为设备0。总线号取决于设备连接到的PCIe根端口(即插槽)以及BIOS配置PCIe总线的方式。(同一插槽通常具有相同的总线号,但可能没有,具体取决于连接到其他PCIe根端口的端口。)

    其余的假设和术语都很好

    软件通过使用I/O端口0xcf8和0xcfc的in/out指令或使用内存映射的配置空间来访问PCI配置空间。PCI配置空间的内存地址范围由BIOS设置。软件通过查看ACPI表找到地址。这些I/O或内存访问转换为PCIe信号的机制完全在根复杂硬件中

    PCI配置空间地址范围的偏移量控制正在访问的设备/寄存器软件。例如,对MMCFG+0的访问访问设备0:0.0的寄存器偏移量0。访问MMCFG+0x1000访问设备0:0.1的寄存器偏移量0,访问MMCFG+0x102000访问设备1:0.2的寄存器偏移量0

    软件读取每个设备地址偏移量3:0处的供应商id/设备id寄存器,以检测该设备地址是否存在设备。如果没有设备,PCI控制器返回0xffffffff。如果存在设备,该设备将返回供应商id