PCIe的全稱是Peripheral Component Interconnect Express,是一種用于連接外設(shè)的總線。 它于2003年提出來(lái),作為替代PCI和PCI-X的方案,現(xiàn)在已經(jīng)成了現(xiàn)代CPU和其他幾乎所有外設(shè)交互的標(biāo)準(zhǔn)或者基石,比如,我們馬上能想到的GPU,網(wǎng)卡,USB控制器,聲卡,網(wǎng)卡等等,這些都是通過(guò)PCIe總線進(jìn)行連接的,然后現(xiàn)在非常常見(jiàn)的基于m.2接口的SSD,也是使用NVMe協(xié)議,通過(guò)PCIe總線進(jìn)行連接的,除此以外,Thunderbolt 3 [2],USB4 [3],甚至最新的CXL互聯(lián)協(xié)議 [4],都是基于PCIe的!
CXL(Compute Express Link)是一種業(yè)界支持的高速緩存一致性互連協(xié)議,用于處理器、內(nèi)存擴(kuò)展和加速器之間的通信。CXL技術(shù)在CPU內(nèi)存空間和附加設(shè)備上的內(nèi)存之間保持一致性,這允許資源共享以獲得更高的性能,減少軟件堆棧的復(fù)雜性,并降低整體系統(tǒng)成本。
所以一旦開(kāi)始往設(shè)備相關(guān)的開(kāi)發(fā)上面走了之后,PCIe可以算是一個(gè)繞不過(guò)的坎。這幾天看了一些和PCIe相關(guān)的資料,這里簡(jiǎn)單的總結(jié)一下,也希望對(duì)大家有所幫助。這篇文章主要會(huì)聚焦在硬件的部分,和操作系統(tǒng)本身沒(méi)有什么太大的關(guān)系,無(wú)論是Windows還是Linux,底層的部分都是非常類似的,文章中也會(huì)提到調(diào)試的方法,不過(guò)會(huì)主要以Linux為主。 那我們就開(kāi)始吧!
1. PCIe總體框圖
首先,我們先從PCIe的基本概念開(kāi)始。PCIe的架構(gòu)主要由五個(gè)部分組成:
Root Complex,
PCIe Bus,
Endpoint,
Port and Bridge,
Switch。
其整體架構(gòu)呈現(xiàn)一個(gè)樹(shù)狀結(jié)構(gòu),如下圖所示:
2. Root Complex(RC)
Root Complex是整個(gè)PCIe設(shè)備樹(shù)的根節(jié)點(diǎn),CPU通過(guò)它與PCIe的總線相連,并最終連接到所有的PCIe設(shè)備上。
主板上最重要、成本最高的兩顆芯片,被稱為北橋和南橋,其中北橋負(fù)責(zé)與處理器對(duì)接,主要功能包括:內(nèi)存控制器、PCI-E控制器、集成顯卡、前/后端總線等,都是速度較快的模塊;而南橋則負(fù)責(zé)外圍周邊功能,速度較慢,主要包括:磁盤控制器、網(wǎng)絡(luò)端口、擴(kuò)展卡槽、音頻模塊、I/O接口等等。
Intel與AMD的新一代處理器,已經(jīng)將傳統(tǒng)北橋的大部分功能都整合在了CPU內(nèi)部,Intel的Clarkdale與Sandybridge處理器則是完全整合北橋芯片,與其搭配的P55/H55/P67/H67等芯片組其實(shí)就是一顆南橋。
Clarkdale的北橋(GPU)和CPU部分示意圖
CPU部分和GPU部分是各自獨(dú)立的,微觀上通過(guò)QPI總線相連,宏觀上被封裝在了一起,接口是與Lynnfield相同的LGA1156。整體上來(lái)看Clarkdale不僅整合了內(nèi)存控制器和PCI-E控制器,還整合了顯示核心,看似更加先進(jìn)。
實(shí)際上,Clarkdale只是將原本放在主板上的北橋芯片,挪到了CPU的鐵蓋下面,本質(zhì)上并沒(méi)有整合任何東西(包括顯卡和內(nèi)存控制器)。但是與之搭配的H55芯片組,確實(shí)只剩下了一顆南橋。北橋的發(fā)熱量遠(yuǎn)高于南橋,由于北橋位于處理器上面,因此用戶再也不用擔(dān)心主板的散熱問(wèn)題了。
目前市面上熱賣的Core i7 8XX和Core i5 7XX處理器,就是基于Lynnfield核心的產(chǎn)品,這是真正意義上整合了北橋的處理器。
用圖片小結(jié)
FSB總線:即前端總線(Front Side Bus),CPU和北橋之間的橋梁,CPU和北橋傳遞的所有數(shù)據(jù)必須經(jīng)過(guò)FSB總線,可以這么說(shuō)FSB總線的頻率直接影響到CPU訪問(wèn)內(nèi)存的速度。
北橋:北橋是CPU和內(nèi)存、顯卡等部件進(jìn)行數(shù)據(jù)交換的唯一橋梁,也就是說(shuō)CPU想和其他任何部分通信必須經(jīng)過(guò)北橋。北橋芯片中通常集成的還有內(nèi)存控制器等,用來(lái)控制與內(nèi)存的通信?,F(xiàn)在的主板上已經(jīng)看不到北橋了,它的功能已經(jīng)被集成到CPU當(dāng)中了。
PCI總線:PCI總線是一種高性能局部總線,其不受CPU限制,構(gòu)成了CPU和外設(shè)之間的高速通道。比如現(xiàn)在的顯卡一般都是用的PCI插槽,PCI總線傳輸速度快,能夠很好地讓顯卡和CPU進(jìn)行數(shù)據(jù)交換。
南橋:主要負(fù)責(zé)I/O設(shè)備之間的通信,CPU要想訪問(wèn)外設(shè)必須經(jīng)過(guò)南橋芯片。
回正題 由于Root Complex是管理外部IO設(shè)備的,所以在早期的CPU上,Root Complex其實(shí)是放在了北橋(MCU)上 [5],后來(lái)隨著技術(shù)的發(fā)展,現(xiàn)在已經(jīng)都集成進(jìn)了CPU內(nèi)部了 [8]。(注意下圖的System Agent的部分,他就是PCIe Root Complex所在的位置。)
另外,雖然是根節(jié)點(diǎn),但是系統(tǒng)里面可以存在不只一個(gè)Root Complex。隨著PCIe Lane的增加,PCIe控制器和Root Complex的數(shù)量也隨之增加。比如,我的臺(tái)式機(jī)的CPU是i9-10980xe,上面就有4個(gè)Root Complex,而我的筆記本是i7-9750H,上面就只有一個(gè)Root Complex。我們?cè)赪indows上可以通過(guò)設(shè)備管理器來(lái)查看:
?
Linux上也類似。下圖是從我的服務(wù)器的主板說(shuō)明書(shū)上截出來(lái)的框圖,用的CPU是EPYC 7742,可以很明顯的看到PEG P0-3,對(duì)應(yīng)著4個(gè)PCIe Controller和Root Complex:[6]
而我們可以通過(guò)lspci命令來(lái)查看所有的Root Complex:
?
$ 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上的設(shè)備通過(guò)PCIe總線互相連接。雖然PCIe是從PCI發(fā)展而來(lái)的,并且甚至有很多地方是兼容的,但是它與老式的PCI和PCI-X有兩點(diǎn)特別重要的不同: PCIe的總線并不是我們傳統(tǒng)意義上共享線路的總線(Bus),而是一個(gè)點(diǎn)對(duì)點(diǎn)的網(wǎng)絡(luò),我們?nèi)绻裀CI比喻成網(wǎng)絡(luò)中的集線器(Hub),那么PCIe對(duì)應(yīng)的就是交換機(jī)了。換句話說(shuō),當(dāng)Root Complex或者PCIe上的設(shè)備之間需要通信的時(shí)候,它們會(huì)與對(duì)方直接連接或者通過(guò)交換電路進(jìn)行點(diǎn)對(duì)點(diǎn)的信號(hào)傳輸。[7]
PCI Bus
PCIe Bus 老式的PCI使用的是單端并行信號(hào)進(jìn)行連接,但是由于干擾過(guò)大導(dǎo)致頻率無(wú)法提升,所以后來(lái)就演變成PCIe之后就開(kāi)始使用了高速串行信號(hào)。這也導(dǎo)致了PCI設(shè)備和PCIe設(shè)備無(wú)法兼容,只能通過(guò)PCI-PCIe橋接器來(lái)進(jìn)行連接。當(dāng)然這些我們都不需要再去關(guān)心了,因?yàn)楝F(xiàn)在已經(jīng)很少看見(jiàn)PCI的設(shè)備了。 關(guān)于PCIe的通訊和包路由交換,我們先到這里,后面會(huì)更深入的介紹。
4. PCIe Device
PCIe上連接的設(shè)備可以分為兩種類型:
Type 0:它表示一個(gè)PCIe上最終端的設(shè)備,比如我們常見(jiàn)的顯卡,聲卡,網(wǎng)卡等等。
Type 1:它表示一個(gè)PCIe Switch或者Root Port。和終端設(shè)備不同,它的主要作用是用來(lái)連接其他的PCIe設(shè)備,其中PCIe的Switch和網(wǎng)絡(luò)中的交換機(jī)類似。
4.1. BDF(Bus Number, Device Number, Function Number)
PCIe上所有的設(shè)備,無(wú)論是Type 0還是Type 1,在系統(tǒng)啟動(dòng)的時(shí)候,都會(huì)被分配一個(gè)唯一的地址,它有三個(gè)部分組成:
Bus Number:8 bits,也就是最多256條總線
Device Number:5 bits,也就是最多32個(gè)設(shè)備
Function Number:3 bits,也就是最多8個(gè)功能
這就是我們常說(shuō)的BDF,它類似于網(wǎng)絡(luò)中的IP地址,一般寫(xiě)作BB:DD.F的格式。在Linux上,我們可以通過(guò)lspci命令來(lái)查看每個(gè)設(shè)備的BDF,比如,下面這個(gè)FCH SMBus Controller就是00:14.0:
$ 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 在我們知道了任何一個(gè)設(shè)備的BDF之后,我們就可以通過(guò)它查看到這個(gè)設(shè)備的詳細(xì)信息了,如下:
$ 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-

?
?
4.2. Type 0 Device和Endpoint
所有連接到PCIe總線上的Type 0設(shè)備(終端設(shè)備),都可以來(lái)實(shí)現(xiàn)PCIe的Endpoint,用來(lái)發(fā)起或者接收PCIe的請(qǐng)求和消息。**每個(gè)設(shè)備可以實(shí)現(xiàn)一個(gè)或者多個(gè)Endpoint,每個(gè)Endpoint都對(duì)應(yīng)著一個(gè)特定的功能。**比如:
一塊雙網(wǎng)口的網(wǎng)卡,可以每個(gè)為每個(gè)網(wǎng)口實(shí)現(xiàn)一個(gè)單獨(dú)的Endpoint;
一塊顯卡,其中實(shí)現(xiàn)了4個(gè)Endpoint:一個(gè)顯卡本身的Endpoint,一個(gè)Audio Endpoint,一個(gè)USB Endpoint,一個(gè)UCSI Endpoint;這些我們都可以通過(guò)lspci或者Windows上的設(shè)備管理器來(lái)查看:
?
$ 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)
說(shuō)到PCIe設(shè)備,腦海里面可能第一反應(yīng)就是有一個(gè)PCIe的插槽,然后把顯卡或者其他設(shè)備插在里面,就像我們上面看到的這樣。但是其實(shí)系統(tǒng)中有大量的設(shè)備是主板上集成好了的,比如,內(nèi)存控制器,集成顯卡,Ethernet網(wǎng)卡,聲卡,USB控制器等等。 這些設(shè)備在連接PCIe的時(shí)候,可以直接連接到Root Complex上面。這種設(shè)備就叫做RCIE(Root Complex Integrated Endpoint),如果我們?nèi)ゲ榭吹脑挘?strong>他們的Bus Number都是0,代表Root Complex。
4.4. Port / Bridge
那么其他的需要通過(guò)插槽連接的設(shè)備呢?這些設(shè)備就需要通過(guò)PCIe Port來(lái)連接了。 在Root Complex上,有很多的Root Port,這些Port每一個(gè)都可以連接一個(gè)PCIe設(shè)備(Type 0或者Type 1)。
本質(zhì)上,所有這些連接其他設(shè)備用的部件都是由橋(Bridge)來(lái)實(shí)現(xiàn)的,這些橋的兩端連接著兩個(gè)不同的PCIe Bus(Bus Number不同)。 比如,一個(gè)Root Port其實(shí)是靠?jī)蓚€(gè)Bridge來(lái)實(shí)現(xiàn)的:一個(gè)(共享的)Host Bridge(上游連接著CPU,下游連接著B(niǎo)us 0)和一個(gè)PCI Bridge用來(lái)連接下游設(shè)備(上游連著的是Bus 0(Root Complex),下游連著的PCIe的設(shè)備(Bus Number在啟動(dòng)過(guò)程中自動(dòng)分配)) [1]。
我們通過(guò)lspci命令可以看到這些橋的存在(注意設(shè)備詳情中的Kernel driver in use: pcieport):
?
+-[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 driver in use: pcieport 注意:是否使用PCIe Bridge和是否通過(guò)插槽連接不能直接劃等號(hào),這取決于你系統(tǒng)的硬件實(shí)現(xiàn),比如,從上面RCIE的截圖中我們可以看到USB Controller作為RCIE存在,而下面EPYC的CPU則不同,USB控制器是通過(guò)Root Port連接的,但是它在主板上并沒(méi)有插槽。
$ 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
如果我們需要連接不止一個(gè)設(shè)備怎么辦呢?這時(shí)候就需要用到PCIe Switch了。 PCIe Switch內(nèi)部主要有三個(gè)部分:
一個(gè)Upstream Port和Bridge:用于連接到上游的Port,比如,Root Port或者上游Switch的Downstream Port
一組Downstream Port和Bridge:用于連接下游的設(shè)備,比如,顯卡,網(wǎng)卡,或者下游Switch的Upstream Port
一根虛擬總線:用于將上游和下游的所有端口連接起來(lái),這樣,上游的Port就可以訪問(wèn)下游的設(shè)備了
另外,這里再說(shuō)明一次 —— 由于PCIe的信號(hào)傳輸是點(diǎn)對(duì)點(diǎn)的,所以Switch中間的這個(gè)總線只是一個(gè)邏輯上的虛擬的總線,其實(shí)并不存在,里面真正的結(jié)構(gòu)是一套用于轉(zhuǎn)發(fā)的交換電路 [9]。 最后,看到這里也許你會(huì)突然想到Root Complex是不是也可以看成是一個(gè)Switch呢?我覺(jué)得這兩個(gè)概念最好還是分開(kāi),雖然從很多框圖上看著確實(shí)很像,只不過(guò)Root Complex沒(méi)有Upstream Port,連接上游的Host Bridge是連接到CPU上,不過(guò)Root Complex內(nèi)部的功能要遠(yuǎn)比Switch復(fù)雜的多,里面不僅僅是簡(jiǎn)單的包轉(zhuǎn)發(fā),比如,后面會(huì)說(shuō)到的PCIe請(qǐng)求的生成和轉(zhuǎn)換等等。
5. 小結(jié)
好了,到這里我們已經(jīng)將PCIe設(shè)備樹(shù)中的主要部件都介紹完畢了。如果我們把所有這些部件連接在一起,那么其整體的結(jié)構(gòu)就是這樣的 [10]:
好的,為了避免文章過(guò)長(zhǎng),我們這一篇就先到這里,后面有時(shí)間再繼續(xù)總結(jié)和PCIe相關(guān)的其他知識(shí),比如配置空間和域,消息和消息路由等等。
PCIe系統(tǒng)舉例
PCIe拓?fù)涮卣鳎簣D的頂部是一個(gè)CPU。這里要說(shuō)明的一點(diǎn)是,CPU被認(rèn)為是PCle層次結(jié)構(gòu)的頂層。PCle只允許簡(jiǎn)單的樹(shù)結(jié)構(gòu),這意味著不允許循環(huán)或其他復(fù)雜的拓?fù)浣Y(jié)構(gòu)。這樣做是為了保持與PCI軟件的向后兼容性,PCI軟件使用一個(gè)簡(jiǎn)單的配置方案來(lái)跟蹤拓?fù)?,不支持?fù)雜的環(huán)境。為了保持這種兼容性,軟件必須能夠與以前相同的方式生成配置周期,總線拓?fù)湟脖仨毰c以前相同。因此,軟件期望找到的所有配置寄存器仍然在那里,并且以它們始終具有的方式運(yùn)行。
在上圖PCIe系統(tǒng)中有幾種設(shè)備類型,Root Complex、Switch、Bridge、Endpoint等,下面分別介紹其概念。
Root Complex:簡(jiǎn)稱RC,CPU和PCle總線之間的接口,可能包含幾個(gè)組件(處理器接口、DRAM接口等),甚至可能包含幾個(gè)芯片。RC位于PCI倒立樹(shù)拓?fù)涞摹案?,并代表CPU與系統(tǒng)的其余部分進(jìn)行通信。但是,規(guī)范并沒(méi)有仔細(xì)定義它,而是給出了必需和可選功能的列表。從廣義上講,RC可以理解為系統(tǒng)CPU和PCle拓?fù)渲g的接口,PCle端口在配置空間中被標(biāo)記為“根端口”。
Bridge:橋提供了與其他總線(如PCI或PCI- x,甚至是另一個(gè)PCle總線)的接口。如圖中顯示的橋接有時(shí)被稱為“轉(zhuǎn)發(fā)橋接”,它允許舊的PCI或PCIX卡插入新系統(tǒng)。相反的類型或“反向橋接”允許一個(gè)新的PCle卡插入一個(gè)舊的PCI系統(tǒng)。
Switch:提供擴(kuò)展或聚合能力,并允許更多的設(shè)備連接到一個(gè)PCle端口。它們充當(dāng)包路由器,根據(jù)地址或其他路由信息識(shí)別給定包需要走哪條路徑。是一種PCIe轉(zhuǎn)PCIe的橋。
Endpoint:處于PCIe總線系統(tǒng)拓?fù)浣Y(jié)構(gòu)中的最末端,一般作為總線操作的發(fā)起者(initiator,類似于PCI總線中的主機(jī))或者終結(jié)者(Completers,類似于PCI總線中的從機(jī))。顯然,Endpoint只能接受來(lái)自上級(jí)拓?fù)涞臄?shù)據(jù)包或者向上級(jí)拓?fù)浒l(fā)送數(shù)據(jù)包。細(xì)分Endpoint類型的話,分為L(zhǎng)agacy PCIe Endpoint和Native PCIe Endpoint,Lagacy PCIe Endpoint是指那些原本準(zhǔn)備設(shè)計(jì)為PCI-X總線接口的設(shè)備,但是卻被改為PCIe接口的設(shè)備。而Native PCIe Endpoint則是標(biāo)準(zhǔn)的PCIe設(shè)備。其中,Lagacy PCIe Endpoint可以使用一些在Native PCIe Endpoint禁止使用的操作,如IO Space和Locked Request等。Native PCIe Endpoint則全部通過(guò)Memory Map來(lái)進(jìn)行操作,因此,Native PCIe Endpoint也被稱為Memory Mapped Devices(MMIO Devices)
如上圖,是一個(gè)高端服務(wù)器系統(tǒng),系統(tǒng)內(nèi)建其他組網(wǎng)接口,如FC,ETH,SAS/SATA等。 “Intel Processor”包含許多組件,大多數(shù)現(xiàn)代CPU架構(gòu)都是如此。這一個(gè)包括一個(gè)PCle端口訪問(wèn)圖形,和2個(gè)DRAM通道,這意味著內(nèi)存控制器和一些路由邏輯已經(jīng)集成到CPU中。這些資源通常統(tǒng)稱為“Uncore”邏輯,將它們與包中的幾個(gè)CPU內(nèi)核及其關(guān)聯(lián)邏輯區(qū)分開(kāi)來(lái)。 Root Complex描述為CPU和PCle拓?fù)渲g的接口,這意味著該部分必須位于CPU中。
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
https://r12f.com/posts/pcie-1-basics/
https://blog.csdn.net/u013253075/article/details/119045277
審核編輯:黃飛
?
評(píng)論