pcie 知识
感官认识
REFCLK
对于控制器来说是 输入
PCIE的REFCLK一般由外部提供
CLKREQ
对于控制器是输出
Downstream/Upstream Component通过assert CLKREQ#来请求REFCLK。
RESET
对于 host 来说 是 输入输出,对于 ep(slave) 来说是输入
WAKEUP
不知道是用于 host 串行 ep , 还是 ep 唤醒host
PCIe上可以接各种控制器
硬盘控制器+硬盘
声卡控制器+音响咪头/耳机
显卡
USB控制器
RS232
PCIe与PCI的不同
1. PCIe数据是串行的,PCI数据是并行的
2. 由于数据是串行的,PCIe 数据要封包,PCI数据不需要封包,地址和数据直接呈现在总线上
3. PCIe 拓扑架构(RC+switch+device)和PCI拓扑架构(bridge+device)有明显的不同
3.1. PCIe bridge 下面 最多有1个 PCIe device. PCI bridge 下面 最多有256个 PCI device.
3.2. 在同一个PCIe总线上,最多只有1个PCIe device . 在同一个PCIe总线上,最多有256个PCIe device .
3.3. PICe device 只和 一个 PCIe bridge的扇出 直接相连,不和 其他的 PCIe bridge 和 PCIe device 直接相连 .
PIC device 和 一个 PCI bridge的扇出 直接相连,也可和多达 255个PCI device 直接相连 .
3.4. PICe bridge在PCIe拓扑中的位置 类似于 PIC device在PCI拓扑中的位置
PCIe的存储空间
https:
https:
https:
PCIe 控制器寄存器空间
Memory Address Space
MMIO
映射出来的空间1:PCI Configuration Space( for all PCI devices)
插槽上插入的设备的信息所在地址
(256Byte)
空间大小
PCI : 16MB
配置前的访问方式
x86中访问方式: 3种
1. 通过 I/O Address Space 0xCF8-0xCFB 和 0XCFC-0xCFF 访问 前 256Byte
2. MMIO访问 , 映射A是 启动就建立好的 , BIOS 中写入基地址就建立了隐性映射A(cpu addr <-> 16MB的配置空间)
arm中访问
1. MMIO访问 , 映射A是 启动就建立好的
配置后的访问方式
x86中访问方式: 3种
1. 配置前的访问方式
2. DMA 访问 前4096Byte
3. MMIO 访问 前4096Byte
arm中访问
1. 配置前的访问方式
2. DMA 访问 前4096Byte
3. MMIO 访问 前4096Byte
================
如果需要 DMA 访问或者 MMIO 访问
需要提前配置 reigon0 的 寄存器 以 建立 cpu addr 到 pcie addr 的映射关系
================
访问方式: 不同的 访问方式对应的 linux驱动 中定义的 struct pci_ops 中的 read 和 write
MMIO访问 是 readl 和 writel
IO访问 是 inl 和 outl
映射出来的空间1:PCIe Configuration Space扩展空间( for all PCIe devices)
插槽上插入的设备的信息所在地址
(4096Byte)
空间大小
PCIe: 256MB
配置前的访问方式 : x86 和 arm 是一样的
1. 通过 I/O Address Space 0xCF8-0xCFB 和 0XCFC-0xCFF 访问 前 256Byte
注意 : 256-4096 Byte 只能在配置后访问
2. MMIO访问 , 映射A是 启动就建立好的 , BIOS 中写入基地址就建立了隐性映射A(cpu addr <-> 256MB的配置空间)
arm中访问
1. MMIO访问 , 映射A是 启动就建立好的
配置后的访问方式
x86中访问方式: 3种
1. 配置前的访问方式
2. DMA 访问 前4096Byte
3. MMIO 访问 前4096Byte
arm中访问
1. 配置前的访问方式
2. DMA 访问 前4096Byte
3. MMIO 访问 前4096Byte
映射出来的空间2:PCIe 插槽上插入的设备上的寄存器空间
访问方式 和 配置空间一样,具体要用那种手段要看 BAR 支持 哪种访问属性
1. DMA&MMIO access
2. IO access
如果需要 DMA 访问或者 MMIO 访问
需要提前
1.配置 reigon0 的 寄存器 以 建立 cpu(mmio) addr 到 pcie addr 的映射关系
2.填充配置空间的 bar 区域
如果需要 DMA 访问或者 MMIO 访问
需要提前
1.配置 reigon0 的 寄存器 以 建立 cpu(mmio) addr 到 pcie addr 的映射关系
2.填充配置空间的 bar 区域
PCIe的映射
Outbound是将 cpu地址 翻译到 PCIe地址
Inbound 是将 PCIe地址 翻译成 cpu地址
host侧 cpu 主动发起的 对 设备寄存器的访问
1. host侧的 cpu addr 经过 pcie rc 的 outbound 转换为 pcie addr
2. pcie 总线上 接的设备 收到 地址(pcie addr)
3. 设备侧pcie ep 的 inbound 将 pcie addr 转换为 设备侧真实存在的寄存器地址(可以是设备的一个version地址)
设备 主动发起的 对 rc侧内存 的访问
1. 设备侧的 cpu addr 经过 pcie ep 的 outbound 转换为 pcie addr
2. pcie 总线上 接的host 收到 地址(pcie addr)
3. 主机侧pcie rc 的 inbound 将 pcie addr 转换为 主机侧真实存在的内存地址(可以是内存中的一个地址)
配置空间
Configuration Address Space的大小为:
256 Bytes/function x
8 functions/device x
32 devices/bus x
256 buses/system
= 16MB。
每个 function(256字节) 的空间分布
每一个PCI功能(Function)都包含256个字节的配置空间(Configuration Space)
前64个字节被称为Header
PCI Spec规定了两种类型的Header:Type1 和 Type0
Type0 Header表示该PCI设备功能 不是桥
Type1 Header表示该PCI设备功能 是桥(Bridge)
后192个字节用于 function-specific
Header Type0
BAR存储了大小和属性
BAR寄存器在PCIe配置空间里面,一个PCIe设备
可能有若干个内部空间(最多6个)需要映射到主机memory地址空间,
设备出厂时,这些空间的大小和属性都写在
Header Type1
PCI与PCIe 非桥设备的访问
PCI
配置空间访问的时候
1.根据idsel 选中设备
2.ce 是表示读还是写
3.总线上的type0地址选中 fuction和 reg
4.配置设备(给设备分配pci地址空间,每个设备的pci地址空间不同).
内存空间访问的时候
读写地址可以,发送到pcie总线,地址符合的设备会回应。
PCIe
配置空间访问的时候
1.发出request , 因为是直连的,所以不需要选中设备
2.request 中的 type cfgrd0表示是配置空间访问
3.request 中的 fuction和 reg 表示
4.配置设备(给设备分配pcie地址空间,每个设备的pcie地址空间不同).
内存空间访问的时候
读写地址可以,发送到pcie总线,地址符合的pcie桥会转发,pcie桥连接的唯一设备会回应。
点到点说的就是这个(PCIe桥唯一连接一个设备).独享带宽说的也是这个
PCI与PCIe 桥设备的访问
PCI
桥设备配置空间访问的时候
1.根据idsel 选中设备
2.ce 是表示读还是写
3.总线上的type0地址选中 fuction 和 reg
4.配置桥的总线number
1.上级桥number
2.自己的number
3.下面的最大的number
5.配置桥下属设备的地址空间
桥下属设备配置空间访问的时候
转发 type1 信号 到下一级(可能转发为type1,也可能转发为type0)
非桥设备内存空间访问的时候
地址如果匹配,转发
PCIe
配置空间访问的时候
1.发出request , 因为是直连的,所以不需要选中设备
2.request 中的 type cfgrd0表示是配置空间访问
3.request 中的 fuction和 reg 表示
4.配置桥
1.上级桥number
2.自己的number
3.下面的最大的number
5.配置桥下属设备的地址空间
桥下属设备配置空间访问的时候
转发 cfgrd1 信号 到下一级(可能转发为 cfgrd1,也可能转发为 cfgrd0)
非桥设备内存空间访问的时候
地址如果匹配,转发
PCIe 在 linux 下的驱动
PCIe 验证
1.PCIe 传递裸数据
2.PCIe 转其他设备
如果转 xhci(USB3.0)
如果PCIe已经处理好BAR,那么在软件上
只需要 处理 xhci 的寄存器空间即可?
PCIe转其他总线
RS232
USB
从用户空间理解PCIe
# lspci
00:00.0 PCI bridge: Texas Instruments Device b010
00:00.0 表示含义为 <bus number>:<device number>.<function number>
bus number : 8bits 最多连接到 256 个bus
device number : 6bits 最多连接到 32 种装置
function number : 3bits 最多每种装置有 8 种功能
0100: 1000:0056 表示含义为 Class ID: Vendor ID Device ID
参数说明
查看所有pci设备
lspci
查看指定的pci设备信息(VID&PID)
lspci -s 02:03.0 -n
查看指定的pci设备信息(前64)
lspci -s 02:03.0 -x
查看指定的pci设备信息(前256)
lspci -s 02:03.0 -xxx
查看指定的pci设备信息(前4096)
lspci -s 02:03.0 -xxxx
lspci 实例
lspci -vvv -s 05:00.0
05:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 10)
Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 17
NUMA node: 0
Region 0: I/O ports at d000 [size=256]
Region 2: Memory at fb104000 (64-bit, non-prefetchable) [size=4K]
Region 4: Memory at fb100000 (64-bit, non-prefetchable) [size=16K]
Capabilities: <access denied>
Kernel driver in use: r8169
Kernel modules: r8169
sudo lspci -xxx -s 05:00.0
05:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 10)
00: ec 10 68 81 07 04 10 00 10 00 00 02 10 00 00 00
10: <01 d0 00 00> <00 00 00 00> <04 40 10 fb> <00 00 00 00>
20: <04 00 10 fb> <00 00 00 00> 00 00 00 00 ec 10 23 01
30: 00 00 00 00 40 00 00 00 00 00 00 00 0a 01 00 00
40: 01 50 c3 ff 08 00 00 00 00 00 00 00 00 00 00 00
50: 05 70 80 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 10 b0 02 02 c0 8c 00 00 00 50 19 00 11 7c 47 00
80: 42 00 11 10 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 1f 08 0c 00 00 00 00 00 02 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 11 d0 03 80 04 00 00 00 04 08 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
/proc/ioports
0cf8-0cff : PCI conf1
1000-ffff : PCI Bus 0000:00
d000-dfff : PCI Bus 0000:05
<d000-d0ff : 0000:05:00.0>
e000-efff : PCI Bus 0000:03
e000-e07f : 0000:03:00.0
f000-f01f : 0000:00:1f.2
f000-f01f : ahci
f020-f023 : 0000:00:1f.2
f020-f023 : ahci
f030-f037 : 0000:00:1f.2
f030-f037 : ahci
f040-f043 : 0000:00:1f.2
f040-f043 : ahci
f050-f057 : 0000:00:1f.2
f050-f057 : ahci
/proc/iomem
80000000-8fffffff : PCI MMCONFIG 0000 [bus 00-ff]
90000000-fbffbfff : PCI Bus 0000:00
e0000000-f1ffffff : PCI Bus 0000:03
e0000000-efffffff : 0000:03:00.0
f0000000-f1ffffff : 0000:03:00.0
fa000000-fb0fffff : PCI Bus 0000:03
fa000000-faffffff : 0000:03:00.0
fb080000-fb083fff : 0000:03:00.1
fb080000-fb083fff : ICH HD audio
fb100000-fb1fffff : PCI Bus 0000:05
<fb100000-fb103fff : 0000:05:00.0>
<fb104000-fb104fff : 0000:05:00.0>
fb104000-fb104fff : r8169
fb200000-fb2fffff : PCI Bus 0000:02
fb200000-fb203fff : 0000:02:00.0
fb200000-fb203fff : nvme
fb300000-fb30ffff : 0000:00:14.0
fb300000-fb30ffff : xhci-hcd
fb310000-fb313fff : 0000:00:1b.0
fb310000-fb313fff : ICH HD audio
fb315000-fb3150ff : 0000:00:1f.3
fb316000-fb3167ff : 0000:00:1f.2
fb316000-fb3167ff : ahci
fb317000-fb3173ff : 0000:00:1d.0
fb317000-fb3173ff : ehci_hcd
fb318000-fb3183ff : 0000:00:1a.0
fb318000-fb3183ff : ehci_hcd
fb319000-fb31900f : 0000:00:16.1
fb31a000-fb31a00f : 0000:00:16.0
fb31b000-fb31bfff : 0000:00:05.4
-------------------
\-[0000:00]-+-00.0
+-01.0-[01]--
+-01.1-[02]----00.0
+-03.0-[03]--+-00.0
| \-00.1
+-05.0
+-1a.0
+-1b.0
+-1c.0-[04]--
+-1c.7-[05]----00.0
$ lspci -s 00:1c.7 -vvv
00:1c.7 PCI bridge: Intel Corporation C610/X99 series chipset PCI Express Root Port #8 (rev d5) (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin D routed to IRQ 30
NUMA node: 0
Bus: primary=00, secondary=05, subordinate=05, sec-latency=0
I/O behind bridge: <0000d000-0000dfff [size=4K]>
Memory behind bridge: <fb100000-fb1fffff [size=1M]>
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff [disabled]
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- VGA16+ MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: <access denied>
Kernel driver in use: pcieport
00:03.0 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 (rev 02) (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 28
NUMA node: 0
Bus: primary=00, secondary=03, subordinate=03, sec-latency=0
I/O behind bridge: 0000e000-0000efff [size=4K] ----------------------------
Memory behind bridge: fa000000-fb0fffff [size=17M] ----------------------------
Prefetchable memory behind bridge: 00000000e0000000-00000000f1ffffff [size=288M] ----------------------------
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA+ VGA16+ MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: <access denied>
Kernel driver in use: pcieport
\-[0000:00]-+-00.0
+-01.0-[01]--
+-01.1-[02]----00.0
+-03.0-[03]--+-00.0
| \-00.1
$ lspci -s 03:00.0 -vvv
03:00.0 VGA compatible controller: NVIDIA Corporation GT216 [GeForce GT 220] (rev a2) (prog-if 00 [VGA controller])
Physical Slot: 4
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 32 bytes
Interrupt: pin A routed to IRQ 44
NUMA node: 0
Region 0: Memory at fa000000 (32-bit, non-prefetchable) [size=16M] ----------------------------
Region 1: Memory at e0000000 (64-bit, prefetchable) [size=256M] ----------------------------
Region 3: Memory at f0000000 (64-bit, prefetchable) [size=32M] ----------------------------
Region 5: I/O ports at e000 [size=128] ----------------------------
Expansion ROM at 000c0000 [disabled] [size=128K]
Capabilities: <access denied>
Kernel driver in use: nouveau
Kernel modules: nvidiafb, nouveau
$ lspci -s 03:00.1 -vvv
03:00.1 Audio device: NVIDIA Corporation GT216 HDMI Audio Controller (rev a1)
Physical Slot: 4
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 32 bytes
Interrupt: pin A routed to IRQ 27
NUMA node: 0
Region 0: Memory at fb080000 (32-bit, non-prefetchable) [size=16K] ----------------------------
Capabilities: <access denied>
Kernel driver in use: snd_hda_intel
Kernel modules: snd_hda_intel
IO address space in x86
I/O Address Space 中的 0xCF8-0xCFF(仅限X86)
x86独有64KB(0x0000-0xffff)的I/O Address Space,arm没有
对于PCIe来说,只用到了 0xCF8-0xCFB 和 0XCFC-0xCFF,用来访问 Configuration Address Space
Configuration Address Space所使用的IO寄存器范围为0xCF8~0xCFF。
其中0xCF8~0xCFB (可以存储32bit)为端口地址,0xCFC~0xCFF为配置数据。
访问方式:
IO汇编
在linux中, outl inl
x86 pc 中的 pcie
1. 南北桥还存在
2. 南北桥一体化了,做成了一个芯片(2023-4-22 22:21:21) https:
3. 主板上没有pci总线了,也没有isa总线了,只有pcie总线和其他总线
4. 南北桥芯片出来的是 各种 "pcie总线桥" 转化过的总线 或者 pcie子总线
南北桥芯片输出的非pcie 接口
音频接口(里面已经集成了了pcie接口的音频控制器)
usb接口(里面已经集成了了pcie接口的usb控制器)
南北桥芯片输出的pcie 接口
pcie接口(主板上连接了pcie网卡+phy)
pcie 插槽
m.2 插槽
PCIe 驱动
分两类
1. pcie控制器 的驱动
也可以称为 host bridge 的驱动, 也可称为 pcie 控制器的驱动.一般由 soc厂家 开发维护
pcie控制器一般设置为rc
功能 :
枚举设备,为pcie设备分配 配置空间和内存空间和中断
2. pcie 设备的驱动
pcie 设备中也有pcie控制器,且必须设置为ep,一般由 pcie板卡厂家 开发维护
功能:
应用 "pcie控制器为其准备好的 内存空间" 初始化 pcie设备
应用 "pcie控制器为其准备好的 中断" 获取软中断, 并注册 中断处理函数
等等
PCIe IO address space
X86采用独立编址的方式,将memory操作与外设IO操作分开了,才有了memory空间和IO空间的区分。
X86平台CPU内部对内存和外设寄存器访问的指令也是不同的。
ARM 架构没有 IO 空间的 概念,不支持 IO 空间
IO空间:
访问外部设备寄存器的地址区域,(PCI支持4GB的IO空间,但是x86平台为64KB),因为X86平台只支持64KB的IO空间,Endpoint为了能在X86上使用,只能把自己的消耗的IO资源限制在64KB以内。由于Endpoint纷纷把IO资源的消耗限制在64KB,因此,大部分其他架构的CPU也把IO空间限制到64KB以内了(不是无法支持,而是根本用不着这么大IO空间)。
————————————————
版权声明:本文为CSDN博主「linjiasen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:
- 如果一个设备只支持 IO Address Space , 那么 可以用在 arm64 平台吗?
支持 , 参考 rk3399的pcie
这个 IO Address Space 这个空间的映射关系及 对应的 region 寄存器来 控制,假设 对应 REGION1
在REGION1 的 desc0(地址为0x028) 中的 [3:0] 表示了 这次映射 是是 "memory IO" 还是 "IO"
在 rockchip_pcie_prog_ob_atu 时
第三个参数为 AXI_WRAPPER_MEM_WRITE 时表示 设置为 "memory IO"
第三个参数为 AXI_WRAPPER_IO_WRITE 时表示 设置为 "IO"
当arm64 对 这块 内存空间 进行ioport 访问 的时候
如果设置为 "memory IO" , 将会产生 一个 TLP, TLP Type 为 CfgRdx或者CfgWrx
如果设置为 "IO" , 将会产生 一个 TLP, TLP Type 为 IORd或者 IOWr
arm64 如何进行 ioport 访问呢?
实际上arm64架构 不支持 ioport , 只支持 iomem
arm64架构的linux 中也有ioport的概念,但实际上是底层走了 iomem,只是呈现出来 在 /proc/ioport 有 映射关系 而已.
即实际 ioport 访问的时候 ,底层 走的 指令是 load 或者 store , 而不是 inb(arm64没有这种指令) 或者 outb(arm64没有这种指令)