1. 程式人生 > >從cpu角度理解PCIe續集

從cpu角度理解PCIe續集

  1. 概述

上篇文章剩下兩個問題,上電掃描PCIe樹和儲存地址到PCIe地址的對映,本篇文章將對這兩個問題做出解答。本文可能會針對某一款晶片做出詳細流程解答,讀者可以只關注整個流程,具體對映機制和暫存器參考晶片datasheet。上篇文章已經瞭解到如何訪問配置空間,前256Bytes可以通過暫存器方式訪問,後面的256B~4k必須通過對映才能訪問,對映無非就是把配置空間對映到儲存地址空間,或者把PCIe裝置空間對映到儲存地址空間。下面開始討論對映關係。

  1. 地址對映關係

PCIe在儲存域地址空間分為三部分,PCIe控制器本身的暫存器、PCIe裝置的配置空間、PCIe裝置空間。暫存器和配置空間由處理器本身決定儲存地址範圍,本款處理器地址範圍如圖 1所示,配置空間地址、暫存器地址、記憶體地址都已經確定。PCIe裝置空間需要程式設計人員去配置Outbound和Inbound暫存器組,確定對映關係

                                                                                                              圖

1

Outbound在PCIe控制器中扮演的角色是將儲存地址翻譯到PCIe域的PCIe地址,Inbound是將PCIe地址翻譯成儲存地址,圖 2是一個完整的RC和EP模型地址翻譯模型,圖中的地址數字僅僅代表一種形態,具體地址應該是什麼在後文中講解。當cpu需要訪問EP的記憶體空間時,首先應該將儲存地址轉換成PCIe地址,在根據TLP到達指定的EP,進而將PCIe地址轉換成EP端的儲存地址。

                                                                                                           圖

2

PCIe地址到儲存地址之間的對映關係由三個暫存器決定(有兩個暫存器組應該是32個暫存器)OB_SIZE、OB_OFFSET_INDEXn、OB_OFFSETn_HI,n的範圍是0~31。在PCIe控制器中是把PCIe地址等分成32塊regions (Regions 0 to 31),每個regions的大小是可以通過程式設計設定OB_SIZE暫存器確定大小,大小有1, 2, 4, or 8 MB,那麼通過Outbound能夠翻譯的地址最大為8M*32=256M。儲存域地址中有5位作為識別32個regions的index,OB_SIZE的大小決定這5位在32位地址上的位置。當OB_SIZE等於0,1,2,3時,index在儲存地址中對應的位置是Bits[24:20], bits[25:21], bits[26:22], and bits[27:23],每個regions翻倍,是不是對應的地址應該按翻倍對齊呢,翻倍就是左移一位資料。OB_SIZE暫存器如圖 3所示。

                                                                                                      圖 3

OB_OFFSET_INDEXn暫存器結構如圖 4所示,n是上一段落提到的index的值。該暫存器第0位是地址翻譯使能位,第31~20位是第n個regions的基地址的31~20位,這裡的取值取決regions的大小,當OB_SIZE 等於0,1,2,3時,bits[31:20], bits[31:21], bits[31:22], and bits[31:23]位相應被使用。OB_OFFSETn_HI暫存器的值是64位PCIe地址中第n個regions的基地址的63~32位,在32位PCIe地址中,該暫存器的值等於0。

                                                                                                    圖 4

配置OutBound翻譯的幾個暫存器也做了詳解,下面根據舉例說明。圖 5中配置空間儲存地址由CPU本身架構所決定,這部分的地址對映才晶片內部完成,不需要由程式設計人員配置。PCIe裝置空間被分成了32等分。假設region大小是2M,PCIe地址是64位,程式中需要對0x9D3A_1234儲存地址做對映, 64位PCIe地址被使用在region 9上,初始化OBOFFSET9_HI值為0x3344 5566, OB_OFFSET9值56Ex xxxx(x的值這裡不關心,看該暫存器結構就很清楚,第0位在地址翻譯時候應該使能位1,這裡僅僅用來講解怎麼做對映,不需要關心後面的Bits) ,下面分析怎麼翻譯到PCIe地址:

  1. 由於是regions大小2M,那麼index應該取地址的bits [25:21],提取0x9D3A_1234儲存地址的bits [25:21得到01001b,該值等於9,那麼該地址應該啟用regions 9 翻譯。儲存地址的bits[20:00]是用做翻譯到PCIe地址的bits[20:00]位,該值也可以理解成reginos 9內的偏移值,值是0x001A 1234。
  2. 生成regions 塊PCIe的基地址,該地址應pcie_base=OBOFFSET9_HI <<32 + OB_OFFSET9的bits[31:21] = 0x 3344 5566 56E0 0000。
  3. 計算PCIe地址,pcie_addr = pcie_base + 儲存地址bits[20:0] =0x3344 5566 56FA 1234。

 

 

                                                                                                          圖 5

 

從上面儲存地址到PCIe地址對映可以看到,通過cpu定址可以直接訪問到PCIe裝置空間,最多可以訪問PCIe裝置空間大小為256M,具體Outbound能夠訪問的大小根據晶片而定,當CPU與FPGA之間有大量資料互動時候也可以採用Inbound方式(Inbound地址翻譯流程如圖 6所示,這裡就不在翻譯),將CPU的記憶體對映到FPGA的定址空間(這裡是站在CPU角度看的,從圖2可以理解具體對映大小還由EP決定),FPGA可以採用DMA方式訪問cpu的記憶體,並且速度很快。有些晶片廠商乾脆採用同核異構方式將CPU於FPGA整合在一起(有的將cpu與dsp整合在一起),兩者之間採用AXI高速匯流排通訊。

                                                                                                      圖 6

  1. 掃描PCIe

掃描樹的流程如下:

  1. 建立儲存地址到PCIe地址對映 (對映方式上面段落已經講解了,固定的PCIe配置空間對映)
  2. 分配PCIe匯流排號
  3. 分配裝置號
  4. 訪問配置空間 (這裡有一個原則讀者需要注意,對PCIe裝置配置空間訪問時,一定要確定匯流排號、裝置號、功能號、暫存器,不然無法找到裝置)
  5. 讀寫BAR0確定PCIe裝置1空間大小
  6. 分配PCIe地址
    1. 分配匯流排號

掃描PCIe匯流排樹時,需要對這些PCIe匯流排進行編號,即初始化PCIe橋(在本文一律指透明橋)的Primary、Secondary和Subordinate Bus暫存器。在Linux核心中採用DFS演算法對PCIe匯流排樹進行遍歷,DFS演算法是按照深度優先的原則遍歷PCIe樹,區域性程式碼如圖 7所示,這裡可以跟蹤pci_scan_bridge函式,函式採用DFS演算法對匯流排進行編號(後期會講解搜尋樹,比較常見hash表、紅黑樹)。

                                                                                     圖 7

    1. 分配裝置號

PCIe裝置的IDSEL訊號與PCIe匯流排的AD[31:0]訊號的連線關係決定了該裝置在這條總線上的裝置號。在配置讀寫匯流排事務的地址週期中,AD[10:0]已經被訊號已經被功能號和暫存器號使用,因此PCIe裝置的IDSEL只能與AD[31:11]訊號連線。上一篇文章中談到CONFIG_ADDR暫存器中的Device Number欄位一共有5位,最大能夠表示32個裝置,這裡只有21位,顯然在兩者之間不能建立一一對映關係。一個PCIe匯流排號下最多可以掛在21個PCIe裝置,那麼多個PCIe匯流排不就可以掛載32個裝置了麼。

    1. 訪問配置空間

在32位PCIe地址空間中,PCIe裝置通常將PCIe配置存放在E2PROM中,PCIe裝置進行上電初始化時,將E2PROM中的資訊讀到PCIe裝置的配置空間作為初始值,由硬體自動完成。BAR0空間儲存了PCIe裝置空間的大小,某些位被設定成不可預讀,當BAR0全部寫入1時,然後在讀取BAR0值,從資料低位看有多少連續位沒有改變。沒有改變的資料位數記錄的該PCIe裝置空間的大小,假如有n位沒有改變,那麼裝置空間大小應該是2的n次方。第0位代表IO/Memory、第2,3位代表32/64位地址、第4位代表是否可預取,具體位定義格式可以直接參考核心PCIe匯流排程式碼,解析BAR函式如圖 8所示。

                                                                                  圖 8

 

    1. 分配PCIe地址

系統軟體根據根據裝置空間大小建立儲存地址PCIe裝置地址空間的對映,給PCIe裝置分配的PCIe基地址寫入到BAR0,如果是64位PCIe地址,那麼BAR1是高32位地址。

  1. 結語

 寫《從cpu角度理解PCIe》文章我參考了部分晶片的datasheet,並結合linux程式碼分析,本文僅僅起到分析流程的作用,具體對映機制和暫存器晶片參考相應晶片datasheet。如有錯誤,還望指正。