NVM Express(NVMe)是一種高性能、可擴展的接口協議,用于通過PCI express(PCIe)總線,實現主機軟件與NVM設備之間的通信。目前,由于NVMe SSD相比于SATA SSD具有更高的吞吐量、更快的訪問速度和更低的功耗,已經被廣泛應用于各種計算領域和存儲系統。
NVMe隊列
NVMe協議采用成對的提交隊列(Submission Queue,SQ)和完成隊列(Completion Queue,CQ)機制。SQ用于存放提交命令,而CQ則用于存放完成信息。隊列狀態信息通過門鈴寄存器(Door Bell,DB)來檢測。這兩個隊列采用了環形隊列結構,隊列可以映射到任何PCIe可訪問的內存中,通常放在主機側內存。對于提交隊列,主機端是生產者,NVMe SSD是消費者。完成隊列的情況剛好相反。因此SQ Tail指針和CQ Head指針由主機更新,而其他兩個指針由NVMe控制器更新。NVMe的隊列結構如圖1所示。
圖1 隊列示意圖
NVMe隊列的深度是固定的,通過Tail和Head來分別指向隊列的首尾位置,隊列實際可用的大小是隊列大小減1,當Head條目指針等于Tail條目指針時,隊列為空。當Head條目指針比Tail條目指針多一個時,隊列為滿。
NVMe協議中根據命令類型將隊列分為了Admin隊列和I/O隊列,Admin隊列用來緩存管理Admin命令,如獲取SSD屬性、創建I/O隊列等。而I/O隊列用來緩存管理I/O命令,如讀、寫、識別等。在一個系統中只能有一對Admin SQ/CQ,但可以存在多對IO SQ/CQ。Admin SQ/CQ僅用來進行Admin命令的交互,I/O SQ/CQ僅用來進行I/O命令的交互。對于多核系統來說,每個核內雖然只有1個I/O CQ,但是可以存在多個I/O SQ,如圖2所示。
圖2 NVMe多隊列示意圖
由于Host端可能存在多個流水線,多隊列的設計可以讓系統的性能最大化。同時,可以通過對不同的隊列設置不同的優先級,來保證高優先級隊列的命令更快完成。NVMe協議中規定Admin SQ/CQ的隊列深度最大可以支持4096(4K),I/O SQ/CQ的隊列深度最大可以支持65536(64K)。在一個實際設計中,SQ的個數和深度的設置可以根據項目需求和硬件資源進行配置。隊列深度的設置主要和系統中隊列消費者和生產者之間的速率有關。
2. NVMe分層結構
NVMe協議棧結構分為應用層和傳輸層兩個層次。在應用層中實現NVMe命令生成、隊列管理和流程控制,而傳輸層則借助PCIe協議進行實現。PCIe協議分為三層,即事務層、數據鏈路層和物理層。事務層負責將數據傳輸請求和響應打包成事務進行傳輸,數據鏈路層則負責數據傳輸的可靠性和流控制,通過鏈路層控制器(Link Layer Controller, LLC)實現。物理層則負責物理傳輸,包括電信號的發射和接收、時序控制和線路管理等。其分層結構圖如圖3所示。首先,在應用層生成NVMe命令傳輸至事務層。其次,在事務層會對上層傳輸的數據添加首部和校驗,封裝成TLP(Transaction Level Packet)傳輸至數據鏈路層。然后,在數據鏈路層會對TLP添加序列號和校驗,封裝成DLLP。最后,在物理層對數據包進行編碼和并轉串處理后,通過SerDes(Serializer/Deserializer)將數據發送至PCIe鏈路中。
圖3 分層結構
由于NVMe協議是基于PCIe協議實現的,下面通過在PCIe拓撲結構中介紹NVMe協議中的SQ、CQ和DB的位置,以及數據在Host和NVMe SSD之間的傳輸流程。NVMe SSD在PCIe拓撲結構中的位置如圖4所示。
圖4 PCIe拓撲結構
PCIe的拓撲結構由三部分組成,根聯合體(Root Complex, RC)、PCIe交換器(PCIe Switch)和端點(Endpoint, EP)。根聯合體位于拓撲結構的根部,最靠近CPU。端點設備位于PCIe的端末。交換機位于根聯合體和端點設備之間。PCIe使用串行鏈路連接,一個鏈路的兩端只能有兩個設備。因此PCIe需要通過PCIe Switch擴展PCIe鏈路后,才能連接多個EP設備。在NVMe存儲結構中,NVMe SSD也作為PCIe的一個EP端掛載在RC上。
NVMe協議中的SQ和CQ位于Host內存中,主機在初始化時根據隊列的個數和深度在主機內存開辟出相應的內存空間,來存放SQ、CQ命令。DB寄存器位于NVMe SSD中,且被映射到BAR(Base Address Register)空間中,Host可以通過訪問BAR空間來更新DB寄存器的值。
當Host需要向NVMe SSD發送命令時,首先將命令存放在主機內存開辟的SQ區域中,其次通過訪問BAR空間的DB寄存器來告訴NVMe SSD到主機端內存區域取走待執行的命令。待命令執行完成后,NVMe SSD向主機內存的CQ區域寫入完成命令。
3. NVMe數據結構
NVMe協議中規定每個提交命令的大小為64字節,完成命令大小為16字節,NVMe命令分為Admin和IO兩類,NVMe的數據塊組織方式有PRP和SGL兩種。提交命令的格式如圖5所示。
圖5 提交命令數據格式
NVMe提交命令的數據格式屬性如下:
(1)Opcode(OPC):命令操作碼,不同操作命令的Opcode都有對應的值;
(2)Fused Operation(FUSE):融合操作,可選字段,用于將兩個命令融合為一條命令;
(3)PRP or SGL for Data Transfer(PSDT):PRP或SGL數據傳輸;
(4)Command Identifier(CID):命令ID;
(5)Namespace Identifier(NSID):命名空間ID;
(6)Metadata Pointer(MPTR):元數據指針;
(7)PRP Entry 1/2:物理區域頁項;
(8)SGL Entry:散列聚合列表。
Admin命令集定義了可以提交到Admin SQ的命令。NVM命令集定義了可以提交到IO SQ的命令。表1和表2分別列出了Admin命令集和NVM命令集中的常用命令、操作碼和簡要的功能描述。
表1Admin命令集
命令 | 必選/可選 | Opcode | 功能 |
刪除I/O提交隊列 | 必選 | 00h | 刪除I/O提交隊列 |
創建I/O提交隊列 | 必選 | 01h | 創建I/O提交隊列 |
刪除I/O完成隊列 | 必選 | 03h | 刪除I/O完成隊列 |
創建I/O完成隊列 | 必選 | 04h | 創建I/O完成隊列 |
識別 | 必選 | 05h | 返回描述設備的信息 |
設置特性 | 必選 | 07h | 設置SSD控制器特性 |
獲取特性 | 必選 | 08h | 讀取SSD控制器特性 |
獲取日志頁 | 必選 | 02h | 讀取日志頁表,如SMART日志 |
命令空間管理 | 可選 | 0Ah | 管理命令空間,如創建和刪除操作 |
表2NVMe命令集
命令 | 必選/可選 | Opcode | 功能 |
清除 | 必選 | 00h | 將緩存內容刷新至非易失性存儲器 |
寫 | 必選 | 01h | 將數據寫入指定邏輯塊 |
讀 | 必選 | 02h | 從指定邏輯塊讀取數據 |
寫入不可糾正的錯誤 | 必選 | 03h | 標記范圍內的邏輯塊無效 |
寫入全0 | 可選 | 05h | 將指定的邏輯塊值設置為0 |
數據集管理 | 可選 | 06h | 指定邏輯塊屬性 |
接下來介紹NVMe協議中的尋址方式。在NVMe協議中定義了兩種尋址方式,PRP和SGL。通過PRP和SGL來記錄Host內存中物理頁的位置。NVMe命令中的PRP和SGL字段用來向NVMe SSD傳遞將要讀寫數據在內存中的位置。NVMe協議中規定Admin命令只能通過PRP告訴NVMe SSD命令在內存中物理地址。而SGL主要是在NVMeoF中使用,因此本設計將采用PRP尋址方式。
Host可以通過配置NVMe Controller的CC.MPS寄存器來設定物理頁的大小,物理頁的大小可設定的范圍是4KB~128MB之間。物理頁對應的地址記錄在PRP Entry中,PRP Entry的數據格式。PRP Entry的數據格式由物理頁起始地址和頁偏移地址兩部分組成,如圖6所示。由于物理地址只能是四字節對齊,因此將偏移地址的最低2bit置為0。此外,圖6中n的取值與設置的物理頁大小有關,例如,將物理頁大小設置為4KB,則n=11,通過偏移地址[11:2]來表示在一個內存頁內的偏移地址。
圖6 PRP Entry格式
一個PRP Entry只能指向一個物理頁。NVMe協議中只定義了兩個PRP Entry,當傳輸數據量大小大于兩個內存頁大小時,PRP Entry2將不指向物理頁,而是指向由若干個PRP組成的PRP List。如圖7所示,NVMe命令中的PRP1指向第一個內存頁,PRP2指向一個新的PRP鏈表的首地址。如果需要指定更大的內存空間可以通過每一個PRP List的最后一個PRP Entry指向新的PRP List。
圖7 PRP原理示意圖
完成命令的數據格式如圖8所示。
圖8 完成命令數據格式
NVMe完成隊列的命令格式屬性如下:
(1)SQ Header pointer:SQ頭指針;
(2)SQ Identifier:SQ ID;
(3)Command Identifier:命令ID;
(4)P:相位標志phase tag,完成隊列沒有head/tail交互,通過相位標志實現完成隊列項的釋放;
(5)Status Field:狀態域。
NVMe工作流程
NVMe協議中的Admin命令和IO命令執行流程相同,主要通過SQ、CQ和DB寄存器三個關鍵部件之間的相互協作來完成。NVMe的命令處理流程分為了8個步驟,如圖9所示。
圖9 NVMe命令處理流程
Host和SSD之間通過更新DB(DoorBell)寄存器的值來實現隊列信息的交互。每個SQ和CQ都擁有一個Head寄存器和Tail寄存器。對于SQ而言,Host是生產者,負責向隊列發送提交命令,SSD是消費者,負責執行命令,因此Host負責更新Tail DB寄存器,SSD負責更新Head DB寄存器。對于CQ而言,SSD是生產者,負責向隊列發送完成命令,Host是消費者,負責檢查完成信息,因此SSD負責更新Tail DB寄存器,Host負責更新Head DB寄存器。而DB寄存器都存在于SSD內,且只能進行寫操作,不能進行讀操作。因此NVMe協議中規定SSD通過完成信息向Host反饋CQ Tail和SQ Head寄存器的值。
NVMe命令處理的步驟如下:
(1)主機提交新的NVMe命令。主機生成新的NVMe命令并添加ID號后,將其存放在SQ Tail指針指向的內存空間中;
(2)主機更新SQ Tail DB寄存器。主機通過Memory Write事務更新SQ Tail DB寄存器的值,以通知NVMe SSD控制器去主機端讀取SQ中緩存的命令;
(3)NVMe SSD讀取命令。NVMe SSD控制器檢測到SQ Tail DB寄存器的變化后,通過Memory Read事務去讀取SQ內緩存的命令,這個過程,NVMe SSD進行突發讀取,一次讀取多條命令,等待取命令完成后更新SQ Head DB寄存器的值;
(4)NVMe SSD執行命令。NVMe SSD控制器根據內部的仲裁機制來執行讀取到的NVMe命令,其執行過程并不是按照隊列的先后順序來執行命令;
(5)NVMe SSD控制器將完成命令寫入CQ。NVMe SSD控制器將NVMe命令的執行結果寫入主機的CQ內存區域中,完成命令包括NVMe命令中的ID號和SQ Head DB寄存器的值;
(6)NVMe SSD通知主機檢查完成命令。NVMe SSD控制器通過Memory Write事務向主機發出MSI-X中斷信號,告知主機檢查CQ中的完成信息。在本設計中,取消了完成隊列的設計,而采用FPGA的并行處理方式,通過主機端實時監測CQ信息,以節省硬件資源和提高NVMe命令處理速度;
(7)主機檢查完成命令。主機從CQ內存中讀取完成信息,并根據狀態字段判斷NVMe命令的執行情況。若命令已經執行完成,主機會釋放該ID號對應的提交命令空間,以便給新的命令使用;
(8)主機更新CQ Head DB寄存器。主機通過Memory Write事務更新CQ Head DB寄存器的值,以通知NVMe SSD控制器CQ中的完成信息已經檢查。
對相關NVM安e設計感興趣的可以看本博客,更多的見csdn用戶: tiantianuser
或視頻見B站 用戶: 專注與守望
審核編輯 黃宇
-
PCIe
+關注
關注
16文章
1339瀏覽量
85034 -
協議分析
+關注
關注
0文章
8瀏覽量
7682 -
nvme
+關注
關注
0文章
251瀏覽量
23212
發布評論請先 登錄
Xilinx FPGA NVMe Host Controller IP,NVMe主機控制器
高性能NVMe主機控制器,Xilinx FPGA NVMe Host Accelerator IP
NVME控制器設計1
NVMe協議訪問能釋放存儲級內存性能和存儲系統的創新
如何選擇合適的NVMe-over-Fabrics方案

PCIe Gen 4協議分析儀的竟然那么強大!
NVMe over Fabrics的優勢是什么?
揭開M.2接口的神秘面紗:NVMe協議與SATA協議的差異
【虹科干貨】FC-NVMe 介紹及性能分析

Emulex引導的光纖通道和NVMe FC協議用戶指南 14.2版

評論