共分2部分,這里是第2部分。
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命令集中的常用命令、操作碼和簡要的功能描述。
表1 Admin命令集
表2 NVM命令集
接下來分析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 NVMe之PRP數據格式
一個PRP Entry只能指向一個物理頁。NVMe協議中只定義了兩個PRP Entry,當傳輸數據量大小大于兩個內存頁大小時,PRP Entry2將不指向物理頁,而是指向由若干個PRP組成的PRP List。如圖7所示,NVMe命令中的PRP1指向第一個內存頁,PRP2指向一個新的PRP鏈表的首地址。如果需要指定更大的內存空間可以通過每一個PRP List的最后一個PRP Entry指向新的PRP List。
圖7 NVMe命令中的 原理示意圖
完成命令的數據格式如圖8所示。
圖8 NVMe完成命令格式
NVMe完成隊列的命令格式屬性如下:
(1)SQ Header pointer:SQ頭指針;
(2)SQ Identifier:SQ ID;
(3)Command Identifier:命令ID;
(4)P:相位標志phase tag,完成隊列沒有head/tail交互,通過相位標志實現完成隊列項的釋放;
(5)Status Field:狀態域。
4 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設計感興趣的可以看本博客,或視頻見B站 用戶: 專注與守望