2024-07-08

https://r12f.com/posts/pcie-1-basics/


Overview

1. PCIe總體框圖

2. Root Complex(RC)

3. PCIe總線(Bus)

4. PCIe Device

4.1. BDF(Bus Number, Device Number, Function Number)

4.2. Type 0 Device和Endpoint

4.3. RCIE(Root Complex Integrated Endpoint)

4.4. Port / Bridge

4.5. Switch

5. 小結

6. 參考資料

?Links

青藤木鳥

民國文藝少女Muqi

無痕的碎碎念

victoryang

小明

PCIe(一) —— 基礎概念與設備樹

?Posted on?2023-05-22??In?01 Binary Life??Views:?6154??Disqus:?0 Comments

PCIe的全稱是Peripheral Component Interconnect Express,是一種用于連接外設的總線。它于2003年提出來,作為替代PCI和PCI-X的方案,現在已經成了現代CPU和其他幾乎所有外設交互的標準或者基石,比如,我們馬上能想到的GPU,網卡,USB控制器,聲卡,網卡等等,這些都是通過PCIe總線進行連接的,然后現在非常常見的基于m.2接口的SSD,也是使用NVMe協議,通過PCIe總線進行連接的,除此以外,Thunderbolt 3?[2],USB4?[3],甚至最新的CXL互聯協議?[4],都是基于PCIe的!

所以一旦開始往設備相關的開發上面走了之后,PCIe可以算是一個繞不過的坎。這幾天看了一些和PCIe相關的資料,這里簡單的總結一下,也希望對大家有所幫助。這篇文章主要會聚焦在硬件的部分,和操作系統本身沒有什么太大的關系,無論是Windows還是Linux,底層的部分都是非常類似的,文章中也會提到調試的方法,不過會主要以Linux為主。

那我們就開始吧!

1. PCIe總體框圖

首先,我們先從PCIe的基本概念開始。PCIe的架構主要由五個部分組成:Root Complex,PCIe Bus,Endpoint,Port and Bridge,Switch。其整體架構呈現一個樹狀結構,如下圖所示:

2. Root Complex(RC)

Root Complex是整個PCIe設備樹的根節點,CPU通過它與PCIe的總線相連,并最終連接到所有的PCIe設備上。

由于Root Complex是管理外部IO設備的,所以在早期的CPU上,Root Complex其實是放在了北橋(MCU)上?[5],后來隨著技術的發展,現在已經都集成進了CPU內部了?[8]。(注意下圖的System Agent的部分,他就是PCIe Root Complex所在的位置。)

另外,雖然是根節點,但是系統里面可以存在不只一個Root Complex。隨著PCIe Lane的增加,PCIe控制器和Root Complex的數量也隨之增加。比如,我的臺式機的CPU是i9-10980xe,上面就有4個Root Complex,而我的筆記本是i7-9750H,上面就只有一個Root Complex。我們在Windows上可以通過設備管理器來查看:

i9-11900Ki7-9750H

Linux上也類似。下圖是從我的服務器的主板說明書上截出來的框圖,用的CPU是EPYC 7742,可以很明顯的看到PEG P0-3,對應著4個PCIe Controller和Root Complex:[6]

而我們可以通過lspci命令來查看所有的Root Complex:

1

2

3

4

5

$ lspci -t -v

-+-[0000:c0]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

+-[0000:80]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

+-[0000:40]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

\-[0000:00]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

3. PCIe總線(Bus)

PCIe上的設備通過PCIe總線互相連接。雖然PCIe是從PCI發展而來的,并且甚至有很多地方是兼容的,但是它與老式的PCI和PCI-X有兩點特別重要的不同:

PCIe的總線并不是我們傳統意義上共享線路的總線(Bus),而是一個點對點的網絡,我們如果把PCI比喻成網絡中的集線器(Hub),那么PCIe對應的就是交換機了。換句話說,當Root Complex或者PCIe上的設備之間需要通信的時候,它們會與對方直接連接或者通過交換電路進行點對點的信號傳輸。[7]

PCI BusPCIe Bus

老式的PCI使用的是單端并行信號進行連接,但是由于干擾過大導致頻率無法提升,所以后來就演變成PCIe之后就開始使用了高速串行信號。這也導致了PCI設備和PCIe設備無法兼容,只能通過PCI-PCIe橋接器來進行連接。當然這些我們都不需要再去關心了,因為現在已經很少看見PCI的設備了。

關于PCIe的通訊和包路由交換,我們先到這里,后面會更深入的介紹。

4. PCIe Device

PCIe上連接的設備可以分為兩種類型:

Type 0:它表示一個PCIe上最終端的設備,比如我們常見的顯卡,聲卡,網卡等等。

Type 1:它表示一個PCIe Switch或者Root Port。和終端設備不同,它的主要作用是用來連接其他的PCIe設備,其中PCIe的Switch和網絡中的交換機類似。

4.1. BDF(Bus Number, Device Number, Function Number)

PCIe上所有的設備,無論是Type 0還是Type 1,在系統啟動的時候,都會被分配一個唯一的地址,它有三個部分組成:

Bus Number:8 bits,也就是最多256條總線

Device Number:5 bits,也就是最多32個設備

Function Number:3 bits,也就是最多8個功能

這就是我們常說的BDF,它類似于網絡中的IP地址,一般寫作BB:DD.F的格式。在Linux上,我們可以通過lspci命令來查看每個設備的BDF,比如,下面這個FCH SMBus Controller就是00:14.0:

1

2

3

4

5

$ lspci -t -v

# [Domain:Bus]

\-[0000:00]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

# Device.Function

? ? ? ? ? ? +-14.0? Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller

在我們知道了任何一個設備的BDF之后,我們就可以通過它查看到這個設備的詳細信息了,如下:

1

2

3

4

5

6

7

8

$ lspci -s 00:14.0 -vv

00:14.0 SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 61)

? ? ? ? Subsystem: Super Micro Computer Inc H12SSL-i

? ? ? ? Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+

? ? ? ? Status: Cap- 66MHz+ UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-

? ? ? ? IOMMU group: 39

Kernel driverinuse: piix4_smbus

? ? ? ? Kernel modules: i2c_piix4, sp5100_tco

另外,由于默認BDF的方式最多只支持8個Function,可能不夠用,所以PCIe還支持另一種解析方式,叫做ARI(Alternative Routing-ID Interpretation),它將Device Number和Function Number合并為一個8bit的字段,只用于表示Function,所以最多可以支持256個Function,但是它是可選的,需要通過設備配置啟用?[1]

4.2. Type 0 Device和Endpoint

所有連接到PCIe總線上的Type 0設備(終端設備),都可以來實現PCIe的Endpoint,用來發起或者接收PCIe的請求和消息。每個設備可以實現一個或者多個Endpoint,每個Endpoint都對應著一個特定的功能。比如:

一塊雙網口的網卡,可以每個為每個網口實現一個單獨的Endpoint;

一塊顯卡,其中實現了4個Endpoint:一個顯卡本身的Endpoint,一個Audio Endpoint,一個USB Endpoint,一個UCSI Endpoint;

這些我們都可以通過lspci或者Windows上的設備管理器來查看:

1

2

3

4

5

6

7

8

9

10

11

$ lspci -t -v

-+-[0000:c0]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

# A NIC card with 2 ports:

|? ? ? ? ? +-01.1-[c1]--+-00.0? Mellanox Technologies MT2892 Family [ConnectX-6 Dx]

|? ? ? ? ? |? ? ? ? ? ? \-00.1? Mellanox Technologies MT2892 Family [ConnectX-6 Dx]

+-[0000:80]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

# A graphic card with 4 endpoints:

|? ? ? ? ? +-01.1-[81]--+-00.0? NVIDIA Corporation TU104 [GeForce RTX 2080]

|? ? ? ? ? |? ? ? ? ? ? +-00.1? NVIDIA Corporation TU104 HD Audio Controller

|? ? ? ? ? |? ? ? ? ? ? +-00.2? NVIDIA Corporation TU104 USB 3.1 Host Controller

|? ? ? ? ? |? ? ? ? ? ? \-00.3? NVIDIA Corporation TU104 USB Type-C UCSI Controller

4.3. RCIE(Root Complex Integrated Endpoint)

說到PCIe設備,腦海里面可能第一反應就是有一個PCIe的插槽,然后把顯卡或者其他設備插在里面,就像我們上面看到的這樣。但是其實系統中有大量的設備是主板上集成好了的,比如,內存控制器,集成顯卡,Ethernet網卡,聲卡,USB控制器等等。這些設備在連接PCIe的時候,可以直接連接到Root Complex上面。這種設備就叫做RCIE(Root Complex Integrated Endpoint),如果我們去查看的話,他們的Bus Number都是0,代表Root Complex。

4.4. Port / Bridge

那么其他的需要通過插槽連接的設備呢?這些設備就需要通過PCIe Port來連接了。

在Root Complex上,有很多的Root Port,這些Port每一個都可以連接一個PCIe設備(Type 0或者Type 1)。

本質上,所有這些連接其他設備用的部件都是由橋(Bridge)來實現的,這些橋的兩端連接著兩個不同的PCIe Bus(Bus Number不同)。比如,一個Root Port其實是靠兩個Bridge來實現的:一個(共享的)Host Bridge(上游連接著CPU,下游連接著Bus 0)和一個PCI Bridge用來連接下游設備(上游連著的是Bus 0(Root Complex),下游連著的PCIe的設備(Bus Number在啟動過程中自動分配))?[1]

我們通過lspci命令可以看到這些橋的存在(注意設備詳情中的Kernel driver in use: pcieport):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

+-[0000:80]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

# This is the Host bridge that connects to the root port and CPU:

|? ? ? ? ? +-01.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse PCIe Dummy Host Bridge

# This is the PCI bridge that connects to the root port and device with a new bus - 0x81:

|? ? ? ? ? +-01.1-[81]--+-00.0? NVIDIA Corporation TU104 [GeForce RTX 2080]

|? ? ? ? ? |? ? ? ? ? ? +-00.1? NVIDIA Corporation TU104 HD Audio Controller

|? ? ? ? ? |? ? ? ? ? ? +-00.2? NVIDIA Corporation TU104 USB 3.1 Host Controller

|? ? ? ? ? |? ? ? ? ? ? \-00.3? NVIDIA Corporation TU104 USB Type-C UCSI Controller

# Host bridge

$ sudo lspci -s 80:01.0 -v

80:01.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Starship/Matisse PCIe Dummy Host Bridge

? ? ? ? Flags: fast devsel, IOMMU group 13

# PCI bridge

$ sudo lspci -s 80:01.1 -v

80:01.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Starship/Matisse GPP Bridge (prog-if 00 [Normal decode])

? ? ? ? Flags: bus master, fast devsel, latency 0, IRQ 35, IOMMU group 13

? ? ? ? Bus: primary=80, secondary=81, subordinate=81, sec-latency=0

? ? ? ? I/O behind bridge: 0000b000-0000bfff [size=4K]

? ? ? ? Memory behind bridge: f0000000-f10fffff [size=17M]

? ? ? ? Prefetchable memory behind bridge: 0000020030000000-00000200420fffff [size=289M]

? ? ? ? ....

Kernel driverinuse: pcieport

注意:是否使用PCIe Bridge和是否通過插槽連接不能直接劃等號,這取決于你系統的硬件實現,比如,從上面RCIE的截圖中我們可以看到USB Controller作為RCIE存在,而下面EPYC的CPU則不同,USB控制器是通過Root Port連接的,但是它在主板上并沒有插槽。

1

2

3

4

5

6

$ lspci -t -v

+-[0000:40]-+-00.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse Root Complex

? ? ? ? ? ? +-03.0? Advanced Micro Devices, Inc. [AMD] Starship/Matisse PCIe Dummy Host Bridge

|? ? ? ? ? +-03.3-[42]----00.0? ASMedia Technology Inc. ASM1042A USB 3.0 Host Controller

# ^====== 40:03.3 here is a Bridge. And USB controller is connected

#? ? ? ? to this Bridge with a new Bus Number 42.

4.5. Switch

如果我們需要連接不止一個設備怎么辦呢?這時候就需要用到PCIe Switch了。

PCIe Switch內部主要有三個部分:

一個Upstream Port和Bridge:用于連接到上游的Port,比如,Root Port或者上游Switch的Downstream Port

一組Downstream Port和Bridge:用于連接下游的設備,比如,顯卡,網卡,或者下游Switch的Upstream Port

一根虛擬總線:用于將上游和下游的所有端口連接起來,這樣,上游的Port就可以訪問下游的設備了

另外,這里再說明一次 —— 由于PCIe的信號傳輸是點對點的,所以Switch中間的這個總線只是一個邏輯上的虛擬的總線,其實并不存在,里面真正的結構是一套用于轉發的交換電路?[9]

最后,看到這里也許你會突然想到Root Complex是不是也可以看成是一個Switch呢?我覺得這兩個概念最好還是分開,雖然從很多框圖上看著確實很像,只不過Root Complex沒有Upstream Port,連接上游的Host Bridge是連接到CPU上,不過Root Complex內部的功能要遠比Switch復雜的多,里面不僅僅是簡單的包轉發,比如,后面會說到的PCIe請求的生成和轉換等等。

5. 小結

好了,到這里我們已經將PCIe設備樹中的主要部件都介紹完畢了。如果我們把所有這些部件連接在一起,那么其整體的結構就是這樣的?[10]

好的,為了避免文章過長,我們這一篇就先到這里,后面有時間再繼續總結和PCIe相關的其他知識,比如配置空間和域,消息和消息路由等等。

6. 參考資料

[1]:?PCI Express Base Specification

[2]:?Thunderbolt? 3 Technology Brief

[3]:?USB4? Specification

[4]:?Compute Express Link? (CXL?) Specification

[5]:?Intel? 3000 and 3010 Chipset Memory Controller Hub (MCH) datasheet

[6]:?H12DSi-NT6 motherboard manual

[7]:?fpga4fun - PCI Express 2 - Topology

[8]:?White Paper: Introduction to Intel? Architecture

[9]:?Crossbar Switch

[10]:?Mindshare - An Introduction to PCI Express

同系列文章:

PCIe(四)—— 物理層

PCIe(三)—— PCIe協議棧,事務層和數據鏈路層

PCIe(二) —— 配置空間

PCIe(一) —— 基礎概念與設備樹

原創文章,轉載請標明出處:Soul Orbit

本文鏈接地址:PCIe(一) —— 基礎概念與設備樹

# pcie?# hardware?# bus

?在Hexo中使用MathJax

PCIe(二) —— 配置空間?

? 2011 –?2024??r12f

Powered by?Hexo?&?NexT.Pisces

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容