Peripheral Component Interconnect (PCI) 及 PCI Express (PCI-E) 的技術標準由 Peripheral Component Interconnect Special Interest Group (PCI-SIG) 管理。
PCI 架構是一種處理器與周邊設備之間的通訊架構。
在 PCI 架構中,所有 PCI 設備都接駁在 PCI 匯流排上。PCI 匯流排上會有主控設備——PCI Host Bridge,負責匯流排的管理,並與上層的處理器溝通。單個匯流排可接入的設備存在上限,因此 PCI 架構提供了 PCI Bus Bridge 元件。PCI Bus Bridge 會提供次一級的 PCI 匯流排,因此其他設備可以接在該 PCI 次一級的匯流排上。
每個匯流排及設備在 PCI 架構下都會被分配一個編號。每個 PCI Bridge(Host 或 Bus)管理的匯流排都給予一個 Bus Number,而接駁在單個匯流排上的設備會依序被分配一個設備編號(Device Number)。我們可以使用 BDF 來定位一個 PCI 設備,BDF 是 Bus, Device, Function 的縮寫。Bus 及 Device 對應到上述的 Bus Number 和 Device Number。單個設備內部可能會依功能切分出不同的 Function Number,若無特殊功能區分,通常為 0。例如,在 NVIDIA 顯卡上,Function 0 是顯卡功能,Function 1 則是音效卡控制器;而在 SR-IOV 架構下,網卡可以創建虛擬網卡供 VM 使用,此時會切分出獨立的 PCI Function。
以上圖中的 NVIDIA STG 2000X 顯示卡為例,它接駁在 PCI Host Bridge 下,所以它的 Bus Number 為 0,而在該匯流排上分配的 Device Number 為 1,Function 0 則指的是主要的顯示卡功能。我們可以使用 bus:device(slot).function
的格式去描述,該顯卡的 BDF 即為 00:01.0
。
在更複雜的架構下,可能存在多個 PCI Host Bridge,每個 PCI Host Bridge 都會獨立管理一個 PCI 設備樹,稱之為 PCI Domain。在這種情況下,需要在 BDF 前面加上 Domain 編號。一般情況下,只有一個 PCI Host Bridge,該編號為 0,因此較完整的 BDF 寫法是 0000:00:01.0
。
在 Linux 系統上,可以使用 lspci
指令查看 PCI 設備資訊。例如,輸入 lspci -nn
後,得到以下輸出:
lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:4660] (rev 02)
00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:460d] (rev 02)
...
00:14.3 Network controller [0280]: Intel Corporation Device [8086:7af0] (rev 11)
...
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA102 [GeForce RTX 3090] [10de:2204] (rev a1)
...
我們拿其中一行出來說明。
00:14.3 Network controller [0280]: Intel Corporation Device [8086:7af0] (rev 11)
0x0280
是 Class Code,PCI-SIG 根據不同類型的周邊設備進行分類。Class Code 分為前後兩段,前半段表示主要類型,0x02
代表網路控制器(Network Controller),後半段是細分類,0x80
表示其他網路設備(Other Network Controller)。比較常見的還有 0x00
代表乙太網路設備,0x07
代表 InfiniBand。8086:7af0
是設備的編號。0x8086
是設備供應商的唯一識別號(Vendor ID),由 PCI-SIG 管理,0x8086
代表 Intel。後段的 7af0
是供應商自行管理的設備型號。最後,rev 11
是設備版本號。PCI Express (PCI-E) 是基於 PCI 架構的一種改進,在通訊方式、傳輸速度等方面有顯著提升。原本在 PCI 架構中負責管理周邊設備的 PCI Host Bridge,被 PCI-E 架構中的 Root Complex (RC) 元件取代(SR-IOV 的 Single Root 就是指 Root Complex)。
在 Linux 系統中,使用 lspci
指令時,會同時顯示 PCI 與 PCI-E 設備。在 PCI-E 架構中,RC 與每個設備之間是點對點傳輸,而非像 PCI 架構那樣透過匯流排傳輸。每個PCI-E設備可以視為獨立的匯流排,因此每個 PCI-E 設備的 Bus ID 都不一樣。
本系列文章主要聚焦於 CPU 與 PCI-E 設備的通訊方式,因此不會展開討論 PCI-E 實現上的細節。從架構圖中可以看到,CPU 與 RAM 之間也經過 Root Complex,這點非常重要。關於這部分的具體內容,我們將在後續文章中詳述。