分享

x86/x86

 drycal 2017-02-03

PCI Express配置空间

PCI-E是用来互联如计算和通信平台应用中外围设备的第三代高性能I/O总线。PCI-E采用了与PCI相同的使用模型和读写(load-store)通信模型,支持各种常见的事务,如存储器读/写、IO/写和配置读/写事务。其存储器、IO和配置地址空间与PCI的地址空间相同。PCI ExpressPCI系统是软件向后兼容的。

PCI-E的配置空间大小为4096字节,如下图所示。其中前256字节是与PCI兼容的配置寄存器,该区域可以用以下两种机制访问:

  • PCI配置访问机制。
  • PCI Express增强型配置机制。

Memory-mapped I/O (MMIO)与port I/O

MMIOport I/O(也称为port-mapped I/OPMIO)是两种CPU与外设之间进行I/O操作的方式。

Port I/O是通过特殊的CPU指令来进行I/O操作,在x86架构上,可以通过指令inout在特定的端口上进行I/O读写。I/O设备拥有与内存不同的地址空间,实现的方式是通过在CPU上额外的I/O pin或者将整个总线赋予端口。

MMIO即内存映射I/O,它是PCI规范一部分,I/O设备被放置在内存空间而不是I/O空。从处理器角度看,内存映射I/O后系统设备访问起来和内存一样。这样访问AGP/PCI-E显卡上的帧缓存,BIOSPCI设备就可以使用读写内存一样的汇编指令完成,简化了程序设计的难度和接口的复杂性。

对软件人员来说,MMIOPort I/O更方便使用。

PCI Express扩展配置空间访问

PCI Express Base Specification Revision 1.1》规范中规定了PCI-E扩展配置空间(2574096字节)的访问方式,即通过MMIO方式访问。

PCI-E规范规定物理内存地址如下表:

规范中只规定了物理地址中A[(20+n-1):20]遵从的规则。因为PCI Express规范最大支持256个总线,所以A[(20+n-1):20]n的最大值为8

PCI Express设备配置空间的物理内存地址基址(Base Address对齐。

最大支持32设备,Device Number A[19:15]5bit

最大8个功能号,Function Number A[14:12]3bit

PCI Express配置空间大小4096字节,因此占用12bit, A[11:8] A[7:2]A[1:0]

注意:上面的nCPU架构中支持的最大总线数。

如下面设备Broadcom NetXtreme II 5709网卡

01:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)

Bus Number:01

Device Number: 00

Function Number: 00

则对应物理地址低21bit为

A[20]为1

A[19:15]为00000

A[14:12]为000

即01:00.0设备PCI Express配置空间的MMIO物理地址低21bit起始地址为0x100000

x86/x86_64 CPU中PCI Express扩展配置空间访问

在上一节中,我们从PCI Express规范来了解扩展配置空间和物理内存地址对应关系,但只提到A[(20+n-1): 0],那么在CPU中的地址高bit64CPUA[63: (20+n)])是由CPU桥片和Firmware来确定。

PCI Express设备配置空间的物理内存地址基址(Base Address对齐。

  • x86/x86_64 CPU中若设置支持的最大总线数为256,则n=8PCI-E设备配置空间的MMIO内存地址是对齐,即PCI Express配置空间占用256MB内存地址空间。
  • x86/x86_64 CPU中若设置支持的最大总线数为64,则n=6PCI-E设备配置空间的MMIO内存地址是对齐,即PCI Express配置空间占用64MB内存地址空间。

x86/x86_64 CPU默认的是支持最大总线为256PCI Express设备配置空间所占的内存物理地址范围为0xe0000000-0xefffffff

下面是Linux内核启动部分打印信息,可以看到BIOS e820图中,将0xe0000000-0xf0000000作为保留区域,给PCI Express配置空间使用,

[ 0.000000] BIOS-e820: 0000000000000000 – 000000000009f800 (usable)

[ 0.000000] BIOS-e820: 000000000009f800 – 00000000000a0000 (reserved)

[ 0.000000] BIOS-e820: 00000000000ca000 – 00000000000cc000 (reserved)

[ 0.000000] BIOS-e820: 00000000000dc000 – 00000000000e4000 (reserved)

[ 0.000000] BIOS-e820: 00000000000e8000 – 0000000000100000 (reserved)

[ 0.000000] BIOS-e820: 0000000000100000 – 000000001fef0000 (usable)

[ 0.000000] BIOS-e820: 000000001fef0000 – 000000001feff000 (ACPI data)

[ 0.000000] BIOS-e820: 000000001feff000 – 000000001ff00000 (ACPI NVS)

[ 0.000000] BIOS-e820: 000000001ff00000 – 0000000020000000 (usable)

[ 0.000000] BIOS-e820: 00000000e0000000 – 00000000f0000000 (reserved)

[ 0.000000] BIOS-e820: 00000000fec00000 – 00000000fec10000 (reserved)

[ 0.000000] BIOS-e820: 00000000fee00000 – 00000000fee01000 (reserved)

[ 0.000000] BIOS-e820: 00000000fffe0000 – 0000000100000000 (reserved)

… …

[ 0.834563] PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem 0xe0000000-0xefffffff] (base 0xe0000000)

[ 0.834729] PCI: MMCONFIG at [mem 0xe0000000-0xefffffff] reserved in E820

Linux中如何读写PCI Express配置空间

通过上面介绍,我们可以计算出某个具体PCI Express设备配置空间的起始物理内存地址,但Linux内核并不能直接读写这些物理地址,需要将这些物理内存地址映射到内核中的逻辑地址后,才可以读写PCI Express配置空间。具体原因,请参考x86/x86_64 CPU中逻辑地址、线性地址与物理地址。

我会在另外一篇文章中单独介绍Linux PCI-E设备配置空间读取与修改内核详细实现。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多